Qus: Remove duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appears only once and return the new length.
Note that even though we want you to return the new length, make sure to change the original array as well in place
Do not allocate extra space for another array, you must do this in place with constant memory.
I tried following code, can anyone help where I am going wrong??
#include<iostream>
#include<vector>
using namespace std;
int removeDuplicates(vector<int> &A) {
int m=A.size();
if(m<=1) return m;
vector<int> :: iterator i=A.begin();
vector<int> :: iterator j=A.begin()+1;
vector<int> :: iterator temp;
while(i!=A.end() && j!=A.end())
{
while(j!=A.end() && *i == *j)
{
temp=j;
j++;
A.erase(temp);
}
i=j;
j++;
}
return A.size();
}
int main()
{
vector<int> vec={0,0,0,0,0,0,0,4,4,7,7,7,7,9};
cout<<"ans="<<removeDuplicates(vec);
return 0;
}
When you increment j, then erase the element there, the elements starting at j+1 are moved down. You're skipping over an element by incrementing.
A better approach would be to simply copy the non-repeating elements from one iterator to the other and setting the new length at the end of the main loop. Your current approach is potentially O(n^2), too slow for practical use.
I think this is that you need. This func loops array from tail to head and counts same values. Then performs shift of already unique values on ununique one.
It doesn't change actual size of vector due process because it would probably involve reallocation of memory inside of vector.
int removeDuplicates(vector<int> &vec) {
int currentVal = vec.size() - 1;
int uniqueNumber = 0;
while (currentVal >= 0) {
++uniqueNumber;
int sameVal = currentVal;
while (sameVal > 0 && vec[sameVal - 1] == vec[currentVal])
--sameVal;
int shiftSize = uniqueNumber;
for (int k = 1; k < shiftSize; ++k) {
vec[sameVal + k] = vec[currentVal + k];
}
currentVal = sameVal - 1;
}
return uniqueNumber;
}
You are asked to use an array. Although vector is similar in many ways, it is not the same. Have a look at the example code below.
In addition you are asked to keep memory allocated the same. You cannot ensure that using vector, it's size can grow / shrink once you add / remove elements and when an element is removed the data in the array behind the vector will be reallocated and rewritten.
int main()
{
int arr[14] = {0,0,0,0,0,4,4,4,4,5,5,5,7,9};
int last_non_duplicate_index = 0;
int current_index = 0;
int size = 14;
int new_size = size;
bool is_last_value = false;
// you can use for interchangeably
while(!is_last_value)
{
current_index++; // move one position ahead
if(current_index < size) // out of bonds check
{
if(arr[last_non_duplicate_index] != arr[current_index]) // value at position of current index is different
{
last_non_duplicate_index++; // increase index of the last value which was not a duplicate by one
arr[last_non_duplicate_index] = arr[current_index]; // write at that index
// e.g. if last index was 0 -> increase it to 1 and rewrite whatsever under arr[1] (current index)
}
else // values are the same
{
new_size--; // devrease the size
}
}
else
{
is_last_value = true; // current_index >= size -> out of bonds
}
}
for (int i = 0; i < new_size; i++)
{
std::cout << "arr[" << i << "]" << " = " << arr[i] << std::endl;
}
std::cout << "New size: " << new_size << std::endl;
return 0;
}
#TC : O(n)
#SC : O(1)
def removeDuplicates(arr,n):
# If array has no elements or only one element, return n
if (n==0 and n==1):
return n
# arr = [1,2,2,3,4,4,4,5,5]
# When i = 0, j= 0 arr=[1,2,2,3,4,4,4,5,5], arr[0] != arr[1], hence arr[0] = arr[0] and j =1, Increment i
# When i = 1, j = 1 arr[j] =[1,2,2,3,4,4,4,5,5]. arr[1] == arr[2], hence increment i
# When i = 2, j = 1 arr[j] = [1,2,2,3,4,4,4,5,5] arr[2] != arr[3], hence arr[1] = arr[2] j = 2, increment i
# When i =3, j = 2 arr[j] = [1,2,3,3,4,4,4,5,5] arr[3] != arr[4], hence arr[2] = arr[3] and j = 3, Increment i
# When i = 4, j = 3 arr[j] =[1,2,3,3,4,4,4,5,5] arr[4] == arr[5], hence increment i
# When i = 5, j = 3 arr[j] = [1,2,3,3,4,4,4,5,5] arr[5] == arr[6], hence increment i
# When i = 6, j = 3 arr[j] = [1,2,3,4,4,4,4,5,5] arr[6] != arr[7], hence arr[3] = arr[6] and j = 4, Increment i
# When i = 7, j= 4 arr[j] = [1,2,3,4,4,4,5,5] arr[7] == arr[8], hence Increment i
# End of for loop
j = 0
for i in range(0,n-1):
if arr[i] != arr[i+1]:
arr[j] = arr[i]
j = j + 1
# Check for the last index element and copy it to a[j]. Increment the j and return j
# When j = 4 arr[j] = [1,2,3,4,5,4,4,5,5] increment j
# j = 5
arr[j] = arr[n-1]
j = j + 1
return j
if __name__=="__main__":
arr = [1,2,2,3,4,4,4,5,5]
#arr = [1,1,2]
#arr = [2,2,2,2,2]
n = len(arr)
print(removeDuplicates(arr,n))
You can do it using iterators like this:
#include<iostream>
#include<vector>
using namespace std;
int removeDuplicates(vector<int> &A) {
int m = A.size();
if(m <= 1) return m;
for (auto it1 = A.begin(); it1 != A.end(); it1++) {
for (auto it2 = it1 + 1; it2 != A.end();) {
if (*it1 == *it2) {
it2 = A.erase(it2);
} else {
it2++;
}
}
}
return A.size();
}
int main()
{
vector<int> vec = { 0, 0, 0, 0, 0, 0, 0, 4, 4, 7, 7, 7, 7, 9 };
cout << "ans=" << removeDuplicates(vec);
return 0;
}
Related
I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue
I got stuck with the following task:
"Write a recursive function that takes a one-dimensional array of 100 randomly set integers and finds the position at which a sequence of 10 numbers begins with the minimum sum".
I've written 2 functions:
int recursiveArrSum(int mass[], int dim = 10, int sum = 0) {
if (dim == 0) return sum;
sum += mass[dim-1];
return recursiveArrSum(mass, --dim, sum);
}
int recArrMinSum(int mass[], int dim=100, int tempSum=100, int idx=0, int addPar=0){
if (dim == 0) return idx;
mass[dim]=mass[addPar];
if (tempSum >= recursiveArrSum(mass)){
tempSum = recursiveArrSum(mass);
idx = dim-1;
//mass[dim]=mass[addPar];
}return recArrMinSum(mass, --dim, tempSum, idx, ++addPar);
1st one (recursiveArrSum) - works fine, but the second one drives me crazy...
I can't understand how I need to iterate an array during evoking the function on last return statement. I made it using for loop, and it works correctly:
for (int i=0; i<91; i++){
int tempS=0;
for (int j=i; j<=i+9; j++){
tempS += arr[j];
cout << tempS<< endl;
}
if (tempS<tempSum) {
tempSum=tempS;
k=i+1;
}
}
but recursion doesn't...
Could anyone suggest me the way for solving this issue?
Open for any questions.
Thanks in advance.
This is how I would do it:
A function that keeps in its arguments the current position, the current sum, the minimum sum and the starting position of this minimum sum. The function also transports as arguments the array (obviously), its size and the dimension of the sum (10 in your case).
void compute(int mass[], int massSize = 100, int dim = 10, int currentPosition = 0, int currentSum = 0, int minSum = 99999, int minPosition = -1)
{
// Before suming the first dim elements, we keep going adding the element at the current position and we increase the current position.
if (currentPosition < dim)
{
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition], minSum, minPosition);
return;
}
// When reaching the end of the array, we print our best solution.
if (currentPosition > massSize)
{
std::cout << "Min sum of " << dim << " elements is " << minSum << ", starting at position " << minPosition << std::endl;
return;
}
// In all the other cases, we check if the current sum is better than the minimum sum. If yes, we update the minimum sum and its starting position. Then call again the function!
if (currentSum < minSum)
{
minSum = currentSum;
minPosition = currentPosition - dim;
}
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition ] - mass[currentPosition -dim], minSum, minPosition);
}
Calling the function is easy: compute(mass, SIZE, 10); where mass is your array, SIZE is its size and 10 is your dimension.
With a dimension equals to 5 in this array:
8; 8; 4; 10; 9; 9; 6; 3; 3; 5; 3; 8; 3; 7; 9; 10; 10; 5; 6; 4; 1; 4; 1; 5; 2; 8; 6; 1; 7; 9;
Min sum of 5 elements is 13, starting at position 20
When writing a recursive function, the first things to do is to think about the exit case, the init cases (if there are any) and the "classic" case when you're in the middle of your search.
Feel free to ask any question, I added some comments to make it clear enough.
It is unclear how your code is supposed to work. To iterate the array and find the smallest sum you do something like this (pseudo code):
int currentSum = sum of elements 0 till 9
int smallestSum = currentSum
int smallestIndex = 0
for (i = 10; i < 100; ++i) {
currentSum = currentSum - mass[ i -10] + mass[i]
if (currentSum < smallestSum) {
smallestSum = currentSum
smallestIndex = i
}
}
As initial guess it takes the sum of the first 10 elements, ie elements 0 till 9. After that it iterates the array. Sum of elements 1 till 10 is the same as sum of elements 0 till 9 minus first element plus element 10. More general: To get the sum in the next iteration, element at i-10 is subtracted and element at i is added.
Not exactly sure what you're allowed to include from the STL, but there's this solution:
// Or std::pair<int, int*>
struct resultPair {
int first;
int* second;
};
// Or std::accumulate
int sumOf(int* arr, size_t s) {
int sum = 0;
for (size_t i=0; i<s; ++i)
sum += arr[i];
return sum;
}
resultPair minSeqOfN(int* arr, size_t s, size_t N) {
if (s < N) throw; // Or however you want to check pre-conditions
int sum = sumOf(arr, N);
if (s == N) return { sum, arr }; // Base case
auto nextRes = minSeqOfN(arr+1, s-1, N);
if (nextRes.first < sum) return nextRes;
else return resultPair{sum, arr};
}
The function keeps calling itself minus the first element, until the sequence size is equal to the input array size (then there's just 1 possible answer).
I have array(of numbers) with size N. I need to find minimum element which is unique,so if arr[5] ={1,2,3,1,2}, answer is 3.
I tried that with following code:
Int n = sizeof(arr)/sizeof(arr[0]);
sort(arr,arr + n);
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++){
if(arr[i] == arr[j]){
remove(arr,arr+n,i);
remove(arr,arr+n,j);
}
}
}
But problem is that this only work if I have 2 identical elements of arr.I could create if conditions for number of identical, but I can have 3 or 4 or 1000,so it will be pretty odd. So what is more elagant way to do this? Thank you in advance.
try this code, this uses an unordered map
int m = 2147483647;
int int_array[] = { 1,2,3,3,1,6,7,7,9 };
unordered_map<int, int> map;
for (int i = 0; i < sizeof(int_array) / sizeof(int_array[0]); i++) {
map[int_array[i]] = map[int_array[i]] + 1;
}
unordered_map<int, int>::iterator itr;
for (itr = map.begin(); itr != map.end(); itr++)
{
if (itr->second == 1) {
if (itr->first < m) {
m = itr->first;
}
}
}
printf("minimum unique is %d", m);
after sorting the array you can count the number of the dublicated members , if the member is unique then its count equals zero :
int main()
{
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof(arr) / sizeof(int);
sort(arr, arr + n);
int count = 0;
int unique = -1;
for (int i = 0; unique == -1 && i < n - 1; ++i) {
if (arr[i] != arr[i + 1]) {
if (count==0)
unique = arr[i];
else
count = 0;
}
else {
count++;
}
}
if (count == 0 && unique ==-1)
unique = arr[n-1];
cout << unique;
return 0;
}
I propose the following code:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[5] = { 1,2,3,2,1 };
int N = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + N);
int index = -1;
// Check first element is different comparing with second one.
// If the array is only one element, then first element is unique
if (N == 1 || arr[0] != arr[1]) {
index = 0;
}
else {
int i = 1;
while (i < N - 1 && index == -1) {
// Check number is different to previous and different to next value
if (arr[i - 1] != arr[i] && arr[i] != arr[i + 1]) {
index = i;
}
else
{
i++;
}
}
if (index == -1) {
// No found, check last element comparing with previous
if (arr[i - 1] != arr[i]) {
index = i;
}
}
}
if (index != -1) {
// Have found min value
cout << "Min not repeated value is " << arr[index] << endl;
}
else {
// All elements are repeated
cout << "No min value" << endl;
}
}
Once the array is sorted, I compare each value with previous and next value to check it is unique. But for first and last element are a special case.
Using what I said in the comments, with an extra bool.
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof( arr ) / sizeof( int );
std::sort( arr, arr + n );
bool match = false;
for ( int i = 0; i < n; ++i ) {
if ( i == n - 1 || arr[i] != arr[i + 1] ) {
if ( match )
match = false;
else
return arr[i];
} else {
match = true;
}
}
return -1; // made up number in case all duplicates
If the two values are equal, then we know that we can't use that value again, so I set match to true. If they are not equal, then if it was already disqualified, I ignore it and set match back to false, otherwise, return that value.
There are more elegant ways to do this; this is just the simplest.
When using the bubble sort method to sort my array from smallest to largest its outputting an unexpected value of: -858993460.
Within the debugger i'm being prompted with "Stack around variable 'numb was corrupted'.
I'm currently using Visual studios to run the code.
I have also ran the same code within a new project with no results.
#include <iostream>
int main()
{
int length = 6;
int temp = 0;
int end = 6;
int numb[] = { 6, 5, 4, 3, 2, 1 };
for (int counter = length - 1; counter > 0; counter--)
{
for (int i = 0; i < end; i++)
{
if (numb[i] > numb[i + 1])
{
temp = numb[i + 1];
numb[i + 1] = numb[i];
numb[i] = temp;
}
}
for (int i = 0; i <= 5; i++)
{
std::cout << numb[i] << " ";
}
std::cout << "\n";
end--;
}
system("pause");
}
In you inner for loop where int i = 0; i < end; i++, you need to set the condition to be i < end - 1. This is because you are already going to be at the end of the array with i + 1 when swapping the indexes around.
I need to get the unique value from 2 int arrays
Duplicate is allowed
There is just one unique value
like :
int arr1[3]={1,2,3};
int arr2[3]={2,2,3};
and the value i want to get is :
int unique[]={1}
how can i do this?
im already confused in my 'for' and 'if'
this was not homework
i know how to merge 2 arrays and del duplicate values
but i alse need to know which array have the unique value
plz help me :)
and here is some code i did
int arr1[3]={1,2,3}
int arr2[3]={2,2,3}
int arrunique[1];
bool unique = true;
for (int i=0;i!=3;i++)
{
for (int j=0;j!=3;j++)
{
if(arr1[i]==arr2[j])
{
unique=false;
continue;
}
else
{
unique=true;
}
if(unique)
{
arrunique[0]=arr1[i]
break;
}
}
cout << arrunique[0];
Assuming:
You have two arrays of different length,
The arrays are sorted
The arrays can have duplicate values in them
You want to get the list of values that only appear in one of the arrays
including their duplicates if present
You can do (untested):
// Assuming arr1[], arr2[], and lengths as arr1_length
int i = 0,j = 0, k = 0;
int unique[arr1_length + arr2_length];
while(i < arr1_length && j < arr2_length) {
if(arr1[i] == arr2[j]) {
// skip all occurrences of this number in both lists
int temp = arr1[i];
while(i < arr1_length && arr1[i] == temp) i++;
while(j < arr2_length && arr2[j] == temp) j++;
} else if(arr1[i] > arr2[j]) {
// the lower number only occurs in arr2
unique[k++] = arr2[j++];
} else if(arr2[j] > arr1[i]) {
// the lower number only occurs in arr1
unique[k++] = arr1[i++];
}
}
while(i < arr1_length) {
// if there are numbers still to read in arr1, they're all unique
unique[k++] = arr1[i++];
}
while(j < arr2_length) {
// if there are numbers still to read in arr2, they're all unique
unique[k++] = arr2[j++];
}
Some alternatives:
If you don't want the duplicates in the unique array, then you can skip all occurrences of this number in the relevant list when you assign to the unique array.
If you want to record the position instead of the values, then maintain two arrays of "unique positions" (one for each input array) and assign the value of i or j to the corresponding array as appropriate.
If there's only one unique value, change the assignments into the unique array to return.
Depending on your needs, you might also want to look at set_symmetric_difference() function of the standard library. However, its treatment of duplicate values makes its use a bit tricky, to say the least.
#include <stdio.h>
#include <stdlib.h>
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
int main()
{
int arr1[5] = {5,4,6,3,1};
int arr2[3] = {5, 8, 9};
int unique[8];
qsort(arr1,5,sizeof(arr1[0]),cmp);
printf("\n");
qsort(arr2,3,sizeof(arr2[0]),cmp);
//printf("%d", arr1[0]);
int i = 0;
int k = 0;
int j = -1;
while (i < 5 && k < 3)
{
if(arr1[i] < arr2[k])
{
unique[++j] = arr1[i];
i++;
}
else if (arr1[i] > arr2[k])
{
unique[++j] = arr2[k];
k++;
}
else
{
i++;
k++;
}
}
//int len = j;
int t = 0;
if(i == 5)
{
for(t = k; t < 3; t++)
unique[++j] = arr2[t];
}
else
for(t = i; t < 5; t++)
unique[++j] = arr2[t];
for(i = 0; i <= j; i++)
printf("%d ", unique[i]);
return 0;
}
This is my codes,though there is a good answer .
I didn't realize the idea that know which array have the unique value.
I also think that the right answer that you chose didn't , either.
Here is my version of the algorithm for finding identical elements in sorted arrays on Python in C ++, it works in a similar way
def unique_array(array0 : (int), array1 : (int)) -> (int):
index0, index1, buffer = 0, 0, []
while index0 != len(array0) and index1 != len(array1):
if array0[index0] < array1[index1]:
buffer.append(array0[index0])
index0 += 1
elif array0[index0] > array1[index1]:
buffer.append(array1[index1])
index1 += 1
else:
index0 += 1; index1 += 1
buffer.extend(array0[index0 : len(array0)])
buffer.extend(array1[index1 : len(array1)])
return buffer