How to switch C++ array elements positions based on specified conditions? - c++

I'm having a little problem with getting my head around this homework task. The task says: "Write a function called MoveSmallest that moves all the minimal integer elements at the start of the array. All the remaining items must stay at their places. (the array and its size are parameters)
Example: the array: 2, 3, 5, 1, 2, 3, 6, 4, 2, 1, 1 changes into 1, 1, 1, 2, 3, 5, 2, 3, 6, 4, 2
void MoveSmallest(int A[],int n)
{
int Min;
for(int i=0;i<n;i++)
{
if(i==0)
{
Min=A[i];
}
else if(A[i]<=Min)
{
Min=A[i];
}
}
So far I've only figured to check which one is the smallest element of the array. I don't have any ideas what to do next.

Once you have found the minimum value, all there is left to do is moving things around in order to have the minimum values at the beginning of the array.
You can do this by permuting the values until you have arrived to the "left" of the array (i.e index 0).
void MoveSmallest(int A[],int n)
{
int Min;
for(int i=0;i<n;i++)
{
if(i==0)
{
Min=A[i];
}
else if(A[i]<=Min)
{
Min=A[i];
}
}
for(int i = 0; i < n; i++)
{
if(A[i] == Min)
{
for(int j = i; j > 0; j--)
{
int tmp = A[j];
A[j] = A[j-1];
A[j-1] = tmp;
}
}
}
}
You could also use std::swap to do the permutation, instead of the temporary variable tmp.

Starting from the end of the array, keep track of how many minimal elements you have encountered. Then whenever you encounter a non-minimum element, move it to the right the number of minimal elements you have encountered so far:
void MoveSmallest(int A[], int n)
{
int min;
//Find min logic
//shift non-min elements and count min elements
int cnt = 0;
for (int i = n-1; i >=0; --i)
{
if (A[i] == min)
cnt++;
else
A[i+cnt] = A[i];
}
//Add min elements
for (int i = 0; i < cnt; ++i)
A[i] = min;
}
This will run in O(n) time and O(1) space.

Since your posts mention "basic C++" but not mention what is "basic", here is another solution. This is under the assumption that creating arrays for "work" purposes is considered "basic C++".
void MoveSmallest(int A[], int n)
{
// get the minimum value
int Min = A[0];
for (int i = 1; i < n; ++i)
{
if (A[i] < Min)
Min = A[i];
}
// get the count of the number of minimum values
int minCount = 0;
for (int i = 0; i < n; ++i)
{
if (A[i] == Min)
++minCount;
}
if (minCount > 0)
{
// create a work array and fill in the first
// minCount values with the minimum value
int *B = new int[n];
for (int i = 0; i < minCount; ++i)
B[i] = Min;
// now fill in the rest of the work array with the values
// in the A[] array that are not equal to Min
int current_pos = minCount;
for (int i = 0; i < n; ++i)
{
if (A[i] != Min)
B[current_pos++] = A[i];
}
// Now copy work array back to A array
for (int i = 0; i < n; ++i)
A[i] = B[i];
// get rid of work array
delete[] B;
}
}
Live Example
This runs in linear time O(n), as opposed to quadratic time O(n*n).
The disadvantage of course is that you need room for the work array, so the memory cost is linear O(n).

Related

Sorting Selection larger number to the right not completing

I am creating a sort selecting that puts the max number to the right. I think i have it mostly done and when i execute the code it works but it does not sort the first two numbers in order from smallest to largest.
When I compile I get 2,1,4,7,9,12,99
int n = 7;
int list[] = { 9, 2, 99, 4, 1, 12, 7};
int maxIndex = n - 1;
for (int i = 0; i < maxIndex-1; i++)
{
int maxNum = i;
for (int j = i+1; j < n; j++)
{
if (list[j] > list[maxNum])
{
maxNum = j;
}
int temp = list[j];
list[j] = list[maxNum];
list[maxNum] = temp;
}
}
Im not too sure if its the for function or it has to do with the swap that i have but i dont think its the swap or else the it wouldn't order the other numbers.
So there are a few problems. The first is that your loop limit is incorrect
for (int i = 0; i < maxIndex-1; i++)
should be
for (int i = 0; i < n-1; i++)
You can get rid of the maxIndex variable.
Second your swap is in the wrong place and you swap the wrong elements. You are supposed to swap the maximum value with the current value, so the swap should go after the j loop and not inside it. It's only after the j loop completes that you know what the maximum value is. Plus what you swap is list[i] (the current value) with list[maxNum] (the maximum value). Like this
int maxNum = i;
for (int j = i+1; j < n; j++)
{
if (list[j] > list[maxNum])
{
maxNum = j;
}
}
int temp = list[i];
list[i] = list[maxNum];
list[maxNum] = temp;
Incidentally I don't like the variable name maxNum because it is not a number it's an index. Maybe maxNumIndex would be a better name?

Why this code is working fine at leetcode but giving segmentation fault at geeksforgeeks?

gfg https://practice.geeksforgeeks.org/problems/subset-sum-problem2014/1
leetcode
https://leetcode.com/problems/partition-equal-subset-sum/
Problem:
Given an array arr[] of size N, check if it can be partitioned into two parts such that the sum of elements in both parts is the same.
Example
Input: N = 4
arr = {1, 5, 11, 5}
Output: YES
Explaination:
The two parts are {1, 5, 5} and {11}.
class Solution{
public:
static int equalPartition(int N, int arr[])
{
int sum = 0;
for (int i=0; i<N; i++)
sum += arr[i];
if (sum % 2 != 0)
return 0;
sum = sum/2;
int row = N+1;
int col = sum+1;
int dp[row][col];
for (int i=0; i<col; i++)
dp[0][i] = 0;
for (int i=0; i<row; i++)
dp[i][0] = 1;
for (int i=1; i<row; i++) {
for (int j=1; j<col; j++) {
if ( j< arr[i-1])
dp[i][j] = dp[i-1][j];
else{
if(j-arr[i-1] > 0){
dp[i][j] =max(dp[i-1][j], dp[i-1][j-arr[i-1]]);
}
else{
dp[i][j] = dp[i-1][j];
}
}
}
}
return dp[row-1][col-1];
}
};
So I signed up to portal out of curiosity to figure whats wrong. I was able to get correct answer with the following code. The code makes slight changes, mostly space compression.
As I suspected, the constraints for N (100) and sum of values in array (1e5) were very critical leading to segmentation fault.
Also instead of j-arr[i-1] > 0, it should be j-arr[i-1] >= 0.
Explanation of space compression:
We only need i-1 th state to compute values of current state i, so 2 arrays of size sum each are enough. I keep a reference curr to remember which of the 2 array is to be considered current and curr^1 would be the previous array. We can further optimize to only single array of size sum, but it is out of scope of the answer.
int equalPartition(int N, int arr[])
{
int sum = 0;
for (int i=0; i<N; i++)
sum += arr[i];
if (sum % 2 != 0)
return 0;
sum = sum/2;
int row = N+1;
int col = sum+1;
int dp[2][col]; // change 1
for (int i=0; i<col; i++)
dp[0][i] = 0;
// for (int i=1; i<row; i++)
// dp[i][0] = 1;
dp[0][0] = 1; // change 2, due to space compression don't need above
int curr = 1; // change 3
for (int i=1; i<row; i++, curr^=1) { // change 4
for (int j=1; j<col; j++) {
dp[curr][j] = dp[curr^1][j]; // change 5
if(j-arr[curr^1] >= 0) // change 6
dp[curr][j] =max(dp[curr][j], dp[curr^1][j-arr[i-1]]); // change 7
}
}
return dp[curr^1][col-1]; // change 8
}
};

ERROR: AddressSanitizer: negative-size-param: (size=-4)

Trying to write some code, and erase() is giving me a runtime error. What's wrong with the way I used erase?
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int size = nums.size();
vector<int> list;
for(int i = 1; i <= size; i++)
list.push_back(i);
for(int i = 0; i < size; i++) {
int num = nums[i];
list[num - 1] = 0;
}
for(int i = 0; i < size; i++) {
if(list[i] == 0) {
list.erase(list.begin() + i);
}
}
return list;
}
};
Here's the problem I am trying to solve
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
Since all the non solutions were marked 0, you can remove all 0's in the vector using list.erase( remove (list.begin(), list.end(), 0), list.end() );
My first suggestion, concentrate on this:
for(int i = 0; i < size; i++) {
if(list[i] == 0) {
list.erase(list.begin() + i);
}
}
You are removing elements from list which changes the size. This will lead to accessing elements beyond your list.

Delete duplicates from array C++

I am trying to create a simple program which calls on 2 functions. The first function takes a partially filled array, loops through it and deletes any duplicate values. When a value is deleted from the array, the remaining numbers are moved backwards to fill the gap i.e. when the function is finished, all null values of the array will be together at the end.
The second function prints the updated array.
My current code is below. At present when I run my code, the console shows:
2 6 0 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460. It should be showing: 1 2 5 6 if it worked correctly.
Also, I am not sure how to move the remaining elements of the array backwards so that the null values will be together at the end.
#include "pch.h"
#include <iostream>
using namespace std;
void deleteRepeats(int *arr, int arraySize, int& posUsed);
void printArray(int *arr, int arraySize);
int main()
{
int arr[10] = { 1, 2, 2, 5, 6, 1};
int posUsed = 6;
int arraySize = 10;
deleteRepeats(arr, arraySize, posUsed);
printArray(arr, arraySize);
return 0;
}
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
for (int i = 0; i < arraySize; i++)
{
for (int j = i; j < arraySize; j++)
{
if (arr[i] == arr[j])
{
for (int k = j; k < arraySize; k++)
{
arr[k] = arr[k + 1];
}
posUsed--;
}
else
j++;
}
}
}
}
void printArray(int *arr, int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
cout << arr[i] << " ";
}
}
I would let the std containers to what you like to do.
Sort the vector
Use erase and unique to delete duplicates.
Here is the code
#include <vector>
#include <iostream>
#include <algorithm>
void print(const std::vector<int> &arr){
for (const auto & i : arr){
std::cout << i <<" ";
}
std::cout <<"\n";
}
int main() {
std::vector<int> arr{1, 2, 2, 5, 6, 1};
print(arr);
std::sort( arr.begin(), arr.end() );
arr.erase( std::unique( arr.begin(), arr.end() ), arr.end() );
print(arr);
}
Ps. Using int *arr, int arraySize is not very C++ like. Please always try to use a proper container (which almost always will be std::vector).
EDIT:
I changed my answer a bit, because I found this speed comparison (and actuallty the whole question answered).
What's the most efficient way to erase duplicates and sort a vector?
Given your assignment constraints (more C-like, than idiomatic C++), you can rewrite your function like this, to make it work:
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
for (int i = 0; i < posUsed; ++i)
{
int duplicates = 0;
int j = i + 1;
// find the first duplicate, if exists
for ( ; j < posUsed; ++j)
{
if ( arr[i] == arr[j] ) {
++duplicates;
break;
}
}
// overwrite the duplicated values moving the rest of the elements...
for (int k = j + 1; k < posUsed; ++k)
{
if (arr[i] != arr[k])
{
arr[j] = arr[k];
++j;
}
// ...but skip other duplicates
else
{
++duplicates;
}
}
posUsed -= duplicates;
}
// clean up (could be limited to the duplicates only)
for (int i = posUsed; i < arraySize; ++i)
arr[i] = 0;
}
It might be easier to imagine the algorithm having separate input and output arrays. Then, in pseudo-code:
for i = 0 to input_array_size-1
Is input[i] equal to input[j] for any j between 0 and i-1?
Yes - do nothing
No - copy input[i] to output
To implement this with shared input and output, you need to have two array sizes, input_array_size and output_array_size. Then, the pseudo-code becomes
output_array_size = 0
for i = 0 to input_array_size-1
Is array[i] equal to array[j] for any j between 0 and output_array_size-1?
Yes - do nothing
No:
copy array[i] to array[output_array_size]
Increase output_array_size
Note: it writes output where the input once was, so the check for duplicates should look at all elements that were output. For example, if your array is 1, 2, 1, 3, 5, 6, 3, then for the last 3 the accumulated output is 1, 2, 3, 5, 6, and the code should compare all these with the current element.
To simplify debugging, where it says "do nothing", you can set current element to -1. This way, if you print your array during execution (for debugging), it will be clearer which elements were removed.
there are only two changes made as you can see
1: you were traversing the whole array as you have declared a posUsed=6 variable which is because there are only 6 elements so in in loops you need to traverse in array upto posUsed index like i<posUsed j<posUsed k<posUsed
2: the second changes is in j loop j=i+1 because you don't need to compare the element of any index with element of the same index you have to compare it with elements after that index. if you compare it with same element it will be same and the program will delete that same element which results in ERROR.
onw more thing is that we don't traverse after posUsed index because after that the array is already empty/zero or null whatever you call it
and if you want to display just the non duplicated elements and not the zero's at the end of the array just add if(arr[i]==0) return; in the printArray function loop before cout statement
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
for (int i = 0; i < posUsed; i++)
{
for (int j = i+1; j < posUsed; j++)
{
if (arr[i] == arr[j])
{
for (int k = j; k < posUsed; k++)
{
arr[k] = arr[k + 1];
}
}
}
}
}
}
using two pointers
and if the array sorted
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0) return 0;
int i = 0;
for(int j = 1; j < nums.size(); j++)
if(nums[j] != nums[i]) nums[++i] = nums[j];
// return new array length
return i + 1;
}
//input: [1, 1, 2, 1] (arr1)
//output: 2 (returned length)
// print unique element
for(int i = 0; i < output; i++) cout << arr1[i] << '\n';
// [1, 2]
time complexity: O(N/2) -> O(N)
space complexity: O(1)
Removing duplicate elements from an unsorted array by O(n^2) complexity.
for (i = 1; i < vec.size(); i++)
{
for (j = 0; j < i; j++)
{
if (vec[i] == vec[j])
{
vec[i] = -1; //Every duplicate element will replace by -1
}
}
}
for (i = 0; i < vec.size(); i++)
{
if (vec[i] != -1)
{
copy.push_back(vec[i]);
/*if you are using an array then store this value into a new array.
first, declare a new array. The new array size will be equal to the
previous array. Like this :
int newArr[sizeOfPreviousArrary];
int j = 0;
newArr[j] = arr[i];
j++;
*/
}
}
Removing duplicate elements from an sorted array by O(n) complexity.
for (i = 0; i < n; i++)
{
if (arr[i] != arr[i+1]){
vec.push_back(arr[i]);
/*if you are using an array then store this value into a new array.
first, declare a new array. The new array size will be equal to the
previous array. Like this :
int newArr[sizeOfPreviousArrary];
int j = 0;
newArr[j] = arr[i];
j++;
*/
}
}
Use map or set for deleting duplicates
void removeDuplicates(int arr[], int n)
{
int i;
// Initialise a set
// to store the array values
set<int> s;
// Insert the array elements
// into the set
for (i = 0; i < n; i++) {
// insert into set
s.insert(arr[i]);
}
set<int>::iterator it;
// Print the array with duplicates removed
cout << "\nAfter removing duplicates:\n";
for (it = s.begin(); it != s.end(); ++it)
cout << *it << ", ";
cout << '\n';
}

Finding the Kth Smallest Element in an unsorted vector (Iteratively)

I'm trying to make a code that returns the kth smallest element in a vector.
For example:
Lets say you have a vector rand which contains elements {0, 3, 2, 5}
And the user inputs 2 as a value for K.
The function should then return element 2 from the vector since it is the 2nd (kth) smallest element in the vector.
so far this is my code:
int iterative_kth_element(vector<int>& vec, size_t k)
{
int index = 0;
int min = vec[0];
for(int i = k;i<vec.size();i--) {
for (int j = 1; j < vec.size();j++) {
if ( min > vec[j] ) {
min = vec[j];
index = i;
}
vec.erase(vec.begin() + index);
if (i == 1) {
return min;
}
}
}
}
it keeps returning some huge number that is not even in the vector.
for(int i = k;i<vec.size();i--)
doesn't seem right, assuming that k is always < vec.size(), then condition i<vec.size() is completely useless here. Instead you might rather add:
for(int i = k; i > 0; i--)
And nested loop should actually check all elements, therefore it should start at 0 (it skips first element):
for (int j = 0; j < vec.size(); j++) {
^
And I believe that
index = i;
was meant to be:
index = j;
And make sure all possible paths of execution return some value, pay attention to warnings the compiler gives you. Put one more return statement at the end of function:
return min;
BUT your main problems are:
you should update min before the nested loop starts the execution
the scope of nested loop shouldn't contain the erase call
Try:
int foo(std::vector<int>& vec, const size_t k)
{
int index = 0;
int min = -1;
for(size_t i = 0; i < k; ++i) {
if (vec.empty()) return min;
min = vec[0];
for (size_t j = 0; j < vec.size(); ++j) {
if (vec[j] < min) {
min = vec[j];
index = j;
}
}
vec.erase(vec.begin() + index);
}
return min;
}
int main() {
int a[] = {0, 3, 2, 5};
std::vector<int> v(a, a+4);
std::cout << foo(v, 2);
}
Start here: http://en.wikipedia.org/wiki/Selection_algorithm
int iterative_kth_element(vector<int>& vec, size_t k)
{
int minIndex, minValue;
for (int i = 0; i < k; i++)
{
minIndex = i;
minValue = vec[i];
for (int j = i+1; j < n; j++)
{
if (vec[j] < minValue)
{
minIndex = j;
minValue = vec[j];
}
}
int tmp = vec[i];
vec[i] = vec[minIndex];
vec[minIndex] = tmp;
}
return vec[k];
}
1/ you have a vector but you almost use it only as an array
2/ consider using an iterator.
3/ you are receiving the vector as a reference, which means modifications on it such as erasing an element is effective out of the scope of the method, do you really want to do that?
Here is some incomplete code for my solution. It only takes 1 pass over the vector. This will run in linear time with respect to vec. Hopefully it clears things up. My previous text is kind of wordy. I left it below this source though.
int iterative_kth_element(vector<int>& vec, size_t k)
{
int mins[k];
//assume first k elements are min
for(int i=0; i<k; i++)
{
mins[i] = vec[i];
}
//TODO:
//sort mins array here
//bubble sort is okay if k is small, or pivot
for(int i=k; i < vec.size(); i++)
{
//since mins is sorted, mins[k-1] is the highest value
if(vec[i] < mins[k-1])
{
mins[k-1] = vec[i];
}
//TODO:
//sort mins array here
//you could do a slick bubble sort starting from
//the back of mins until you find the location
//for the new min item
}
return mins[k-1];
}
//previous text
If you're finding a the kth smallest item. You should initialize an array with the first k item. Or store the indexes into vec where the smallest items are found.(would start with 0,1,2,3,...,k)
int index = 0;
int min = vec[0];
should be
int* mins = new int[k];
for(int i=0; i < k; i++) {
mins[i] = vec[i];
}
I would also recommend keeping this array of k smallest integers sorted. If you know where the largest item is, you only have to check each element in vec against the largest item in mins. You'll need a sort method though, which will be called everytime you find something smaller than one of your mins.
After one iteration of vec, you should have the k smallest items in that array. Just return the largest item. Stored at location 0 or k-1 in your array.
Something else to note: If k is greater than vec.size() / 2, you should look for the (vec.size() - k) largest item.
This should be log(k*n) time with a maximum memory footprint of 1.5n(the case where k is exactly vec.size()/2 is the worst case).
where n is the size of vec and k is the parm in the function.(k's upper limit is n/2 if you implement that note).
Worst case scenario is getting a list of numbers in descending order with k being half the size of n.
The array of integer numbers is set.
To delete from the array all positive elements, which allocated
between maximal and minimal elements.
To calculate the sum of negative cells of array.
To calculate the minimum of prime elements