replaces duplicate values in an array with -1 [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
Write a function that replaces duplicate values in an array with -1.
Assume that an array of positive numbers such as {1, 2, 5, 4, 2, 7, 1, 2} is passed to your function.
You must check duplicate values in this array and replace them with -1 except the first appearance.
Your final array of {1, 2, 5, 4, 2, 7, 1, 2} should look like {1,2,5,4,-1, 7, -1,-1}
this is my question can someone figure out ?
{
for(j=i+1; j<size; j++)
{
/* If any duplicate found */
if(arr[i] == arr[j])
{
/* Delete the current duplicate element */
for(k=j; k < size - 1; k++)
{
arr[k] = arr[k + 1];
}
/* Decrement size after removing duplicate element */
size--;
/* If shifting of elements occur then don't increment j */
j--;
}
}
}

In C++, you would do this exactly as you would do manually, with your brain.
Iterate over all elements in the array
Count the number of occurences of an element
If this element is more than one time present, then replace it.
For counting we will use a hash map, so an std::unordered_map. Please read here about that.
The very simple code would then look like this:
#include <iostream>
#include <vector>
#include <unordered_map>
int main() {
std::vector testData{ {1, 2, 5, 4, 2, 7, 1, 2} };
std::unordered_map<int, unsigned int> counter{};
for (int& i : testData) {
counter[i]++;
if (counter[i] > 1)
i = -1;
}
for (const int k : testData)
std::cout << k << ' ';
}

Maybe something like this:
#include <stdio.h>
#include <stdlib.h>
void replaceDuplicates(int *arr, int n)
{
int *differents = malloc(n * sizeof(n));
int iterator = 0;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(arr[i] == differents[j])
{
arr[i] = -1;
}
}
if(arr[i] != -1)
{
differents[iterator++] = arr[i];
}
}
}
int main()
{
int arr[8] = {1, 2, 5, 4, 2, 7, 1, 2};
replaceDuplicates(arr, 8);
for(int i = 0; i < 8; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
Note that I haven't tested this code that much. You should probably improve it
This code outputs:
1 2 5 4 -1 7 -1 -1

Related

Removing duplicates from a sorted array in c++

I am trying to remove the duplicates from sorted array.Code is giving correct output for one test case but fails to give correct output for multiple test cases.I am getting correct output with other methods but what is wrong with this method? How can I solve this problem?
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int a[n],i,k,temp,count;
for(i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
count=0;
for(i=0;i<n;i++){
if(a[i-1]-a[i]==0){
temp = a[i];
count++;
for(k=i;k<n;k++){
a[k] = a[k+1];
}
}
}
for(i=0;i<n-count;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
}
Variable length arrays like this
int a[n],i,k,temp,count;
is not a standard C++ feature. Instead you should use the standard container std::vector<int>.
This if statement
if(a[i-1]-a[i]==0){
invokes undefined behavior when i is equal to 0 due to the expression a[i-1].
The same problem exists in this for loop
for(k=i;k<n;k++){
a[k] = a[k+1];
}
when k is equal to n - 1 due to the expression a[k+1].
Also it is inefficient to copy all elements after the found duplicated element each time when such an element is found.
Pay attention to that there is the standard algorithm std::unique that can be used instead of your loops.
If to use the for loop then you may implement something like the following
#include <iostream>
int main()
{
int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
if ( i == 0 || a[i] != a[n-1] )
{
if ( i != n ) a[n] = a[i];
++n;
}
}
for ( size_t i = 0; i < n; i++ )
{
std::cout << a[i] << ' ';
}
std::cout << '\n';
return 0;
}
The program output is
1 2 3 4 5
If to use the standard algorithm std::unique then the solution will be simpler because there is no need to write your own for loop.
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
auto last = std::unique( std::begin( a ), std::end( a ) );
for ( auto first = std::begin( a ); first != last; ++first )
{
std::cout << *first << ' ';
}
std::cout << '\n';
return 0;
}
The program output is the same as shown above that is
1 2 3 4 5
I see two major problems with your code, both are out-of-bounds reads from an array:
if(a[i-1]-a[i]==0) will at one point be called with i==0, accessing element a[-1].
And here:
for(k=i;k<n;k++){
a[k] = a[k+1];
}
in the last loop iteration, when k == n-1 array element a[n] will be accessed, which is also an out-of-bounds access.

Initialize matrix with all the combinations from an array of objects in C++

I'm a newbie programmer trying to solve the following problem: I need to initialize a matrix with all the combinations from a array of objects so I can extract the values and perform certain calculations afterwards for each set of objects, in this case I used a struct for X, Y coordinates to represent the data. The entire data set consists on 35 coordinates, for now I'm dealing with as few data as possible, an input array of size 4, meaning 4 (n) combinations of 3 (r) objects. The program seems to work fine until I print the 4x3 matrix and find out I was only able to store the first combination, and after tinkering with the program I got stuck since I didn't code this program entirely. Could someone suggest me a solution so the matrix gets initialized correctly? I'd highly appreciate it.
#include <iostream>
#define n 4 //data set size
#define r 3 // combination size
using namespace std;
struct Points{
double x, y;
};
void Combination(Points Data [n], Points CombinationMatrix [][r],int start, int currLen, bool check []) {
// Return if the currLen is more than the required length.
if(currLen > r)
return;
// If currLen is equal to required length then add the sequence.
else if (currLen == r){
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
if (check[i] == true){
CombinationMatrix[i][j] = Data[j];
}
}
}
return;
}
// If start equals to len then return since no further element left.
if (start == n)
{
return;
}
// For every index we have two options.
// First is, we select it, means put true in check[] and increment currLen and start.
check[start] = true;
Combination(Data, CombinationMatrix, start + 1, currLen + 1, check);
// Second is, we don't select it, means put false in check[] and only start incremented.
check[start] = false;
Combination(Data, CombinationMatrix, start + 1, currLen, check);
}
int main()
{
Points Data [n] = { {1, 1} , {2, 7} , {3, 6} , {4, 13}}; //, {5,9} ,
//{6, 7} , {7, 12} , {8, 14} , {9, 17} , {10, 23} ,
//{11,28} , {12, 63} , {13, 45} , {14, 68} , {15, 32} ,
//{16,98} , {17, 115} , {18, 116}, {19, 112}, {20, 115},
//{21, 88} , {22, 86} , {23, 106}, {24, 136}, {25, 158},
//{26, 198}, {27, 128} , {28, 187}, {29, 112}, {30, 149},
//{31, 279}, {32, 224} , {33, 222}, {34, 260}, {35, 166}};
Points CombinationMatrix [n][r];
bool check[n];
for(int i = 0; i < n; i++){
check[i] = false;
}
Combination(Data, CombinationMatrix, 0, 0, check);
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
cout << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << " ";
}
cout << endl;
}
return 0;
}
I suggest that you have a look at std::prev_permutation.
If you have a std::vector<Data> points, then you can get all permutations via
do {
// Do something with the current permutation
for ( int i = 0; i < points.size(); ++i ) {
std::cout << points[i] << ' ';
}
std::cout << '\n';
} while ( std::prev_permutation(points.begin(),points.end()) );
Since this gives you points.size()! (Factorial) combinations, I would not store it in a matrix unless you have a very good reason to do so.
std::prev_permutation uses the lexicographically smaller. Thus, you need to overload the operator < for Data.
inline bool operator< (const Data& lhs, const Data& rhs){
/* do actual comparison e.g.*/
return ((lhs.x <rhs.x) && (lhs.y <rhs.y));
}
The following generates combinations of your array using std::prev_permutation.
Note that this is accomplished by using a bool vector that starts with r of those bits set to true, and on each iteration the bits in the bool vector have their positions changed.
The following uses std::vector<Point> instead of hard-coded arrays. This adds flexibility in that you don't have to guess how many combinations will be generated.
#include <iostream>
#include <vector>
#include <algorithm>
struct Points {
double x, y;
};
std::vector<std::vector<Points>> Combination(std::vector<Points>& Data, int n, int r)
{
// The returned vector
std::vector<std::vector<Points>> retVect;
// Array of bools
std::vector<bool> bits(n);
// Fill the first r positions of the bool array to true
std::fill(bits.begin(), bits.begin() + r, true);
// Our temporary 1 dimensional array we use when building a single combination
std::vector<Points> tempV;
do
{
tempV.clear();
for (int i = 0; i < n; ++i)
{
// for each item in the bool array that's true, add that to the vector
if (bits[i])
tempV.push_back(Data[i]);
}
// add this combination to vector of combinations
retVect.push_back(tempV);
// rearrange the bits
} while (std::prev_permutation(bits.begin(), bits.end()));
return retVect;
}
int main()
{
std::vector<Points> Data = { {1, 1}, {2, 7}, {3, 6}, {4, 13} };
auto CombinationMatrix = Combination(Data, 4, 3);
for (size_t i = 0; i < CombinationMatrix.size(); i++) {
for (size_t j = 0; j < CombinationMatrix[i].size(); j++) {
std::cout << "{" << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << "} "; }
std::cout << std::endl;
}
}
Output:
{1,1} {2,7} {3,6}
{1,1} {2,7} {4,13}
{1,1} {3,6} {4,13}
{2,7} {3,6} {4,13}

How to compare each element of one array to another if present then print Yes otherwise no

#include<iostream>
using namespace std;
int main()
{
int a[8] = { 1, 2, 3, 6, 4, 8, 12, 5 };
int b[6] = { 1, 3, 12, 5, 9, 10 };
for (int i = 0; i < 8; i++)
{
for(int j=0;j<6;j++)
{
if(b[j]==a[i])
{
cout<<"Yes"<<endl;
}
}
cout<<"NO"<<endl;
}
}
i have to compare these array and of element of second array is present in first array then print yes else no
.
I am getting output as
Yes
NO
NO
Yes
NO
NO
NO
NO
Yes
NO
Yes
NO
I have to get output like this
yes
yes
yes
yes
No
No
The primary point to mention here is that, once you've found a match, you need to break; out of the inner loop.
Also, you need to make sure to print either "yes" or "no". As your program currently stands, it will unconditionally print "no" after the inner loop. You can make use of a flag to accomplish that.
Finally, as your logic states, "....of element of second array is present in first array", you need to change the loop structure to reflect that. The outer loop should be used to index the second array b whereas, in the inner loop, you should be traversing the first array a.
You need to do something like (pseudo code, not tested)
for (int j=0; j<6; j++) {
int flag = 0; //reset the flag
for(int i=0; i<8; i++) {
if(b[j]==a[i])
{
cout<<"Yes"<<endl;
flag = 1;
break;
}
}
if (!flag) cout<<"NO"<<endl;
}
Per your stated goal in your question, you should be enumerating your second array (b[]) as your outer loop, hunting for each of its values within your first array (a[]) as the inner loop, and most importantly, breaking the loop with detection (code outside the inner loop knows you broke early) if you found a match and thus know whether Yes or NO should be printed
In short, your algorithm is backwards and still not complete. Fixing the algorithm and using ranged-for as the enumeration method (use it or use subscripting like you are now, up to you), gives us:
#include <iostream>
int main()
{
int a[8] = { 1, 2, 3, 6, 4, 8, 12, 5 };
int b[6] = { 1, 3, 12, 5, 9, 10 };
for (auto x : b)
{
bool found = false;
for (auto y : a)
{
if (x == y)
{
found = true;
break;
}
}
std::cout << (found ? "Yes" : "NO") << '\n';
}
}
Output
Yes
Yes
Yes
Yes
NO
NO
The whys of your broken algorithm have been already given by the other answers. I would like to give you a hint that can help to improve it in terms of time of execution (once fixed, of course).
Note that two nested loops means a complexity of O(N*M), where N is the length of a and M is the length of B.
For you are working with integers, if you can accept to spend a few bytes of space (O(N)) for a set, you can reduce the complexity to O(N+M).
Moreover, the whole code seems to me even easier to understand:
#include<iostream>
#include<unordered_set>
int main() {
int a[8] = { 1, 2, 3, 6, 4, 8, 12, 5 };
int b[6] = { 1, 3, 12, 5, 9, 10 };
std::unordered_set<int> check{a, a+8};
for(int j=0; j<6; j++) {
if(check.find(b[j]) != check.cend()) {
std::cout << "Yes" << std::endl;
} else {
std::cout << "NO" << std::endl;
}
}
}
The basic idea is this:
Iterate over a and put all the values in your set
Iterate over b and check if the set contains the _i-th_value
The second step doesn't require anymore to iterate over a for each value in b. Therefore the overall complexity is reduced (in the average case at least - see the documentation of std::unordered_set for further details).
A more C++ way to do it would be to use std::find (C++11 inside):
#include <algorithm>
#include <iostream>
int main()
{
int a[8] = { 1, 2, 3, 6, 4, 8, 12, 5 };
int b[6] = { 1, 3, 12, 5, 9, 10 };
for (auto bi : b)
{
bool found = std::find(std::begin(a), std::end(a), bi) != std::end(a);
std::cout << (found ? "Yes" : "No") << '\n';
}
}
I did change in your program and it gives the expected output.
for (int i = 0; i < 6; i++)
{
int flag = 0;
for(int j=0;j<8;j++)
{
if(b[i]==a[j]) // take b array value and compare with all elements of a.
{
cout<<"Yes"<<endl;
flag = b[i];
break;
}
}
if (b[i] != flag)
cout<<"NO"<<endl;
}

Sorting an array to another array C++

My program have to sort an array in another array.
When I run the program it prints 1 2 3 -858993460 5 -858993460 7.
I can not understand where the mistake is in the code.
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[N];
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1] = arr[j];
}
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
return 0;
}
Okay lets face the problems in your code.
The "weird" numbers you see there, came from the uninitialzied array sort_arr. What do I mean by uninitialized? Well sort_arr is a little chunck somewhere in your memory. Since a program usually does not clear its memory and rather claims the memory it used as free, the chunk of sort_arr may contain bits and bytes set by another program. The numbers occure since these bytes are interpreted as an integer value. So the first thing to do would be to initialize the array before using it.
sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
Now why did these numbers occure? Well you're probably expecting your algorithm to set all values in sort_arr which would result in an sorted array, right? Well but your algorithm isn't working that well. See this line:
sort_arr[arr[j] - 1] = arr[j];
What happens when j is 1? arr[1] is then evaluated to 17 and 17 - 1 equals 16. So sort_arr[arr[1] - 1] is the same as sort_arr[16] which exceeds the bounds of your array.
If you want to program a sorting algorithm by your self than I would recommend to start with an simple bubble sort algorithm. Otherwise, if you only need to sort the array have a look at the algorithm header. It is fairly simple to use:
#include <iostream>
#include <algorithm>
#include <iterator> // << include this to use begin() and end()
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
copy(begin(arr), end(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
cout << endl;
}
By the way. You're looking for the biggest value in your array, right? After you have sorted the array sort_arr[N - 1] is the biggest value contained in your array.
If you want to sort a array into another array then one way is you make a copy of the array and then use the sort function in the standard library to sort the second array.
int arr[10];
int b[10];
for(int i=0;i<10;i++)
{
cin>>arr[i];
b[i]=arr[i];
}
sort(b,b+10);
// this sort function will sort the array elements in ascending order and if you want to change the order then just add a comparison function as third arguement to the sort function.
It seems that you think that sort_arr[arr[j] - 1] = arr[j] will sort arr into sort_arr. It won't.
Sorting is already written for you here: http://en.cppreference.com/w/cpp/algorithm/sort You can use that like this:
copy(cbegin(arr), cend(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
Live Example
My guess is this is an attempt to implement a type of counting sort. Note that variable length arrays aren't normally allowed in C++ or some versions of C. You could use _alloca() to allocate off the stack to get the equivalent of a variable length array: int * sort_arr = (int *)_alloca(max * sizeof(int)); .
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
// assuming range of values is 1 to ...
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[max];
for (int i = 0; i < max; i++)
{
sort_arr[i] = 0;
}
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1]++;
}
for (int i = 0; i < max; i++)
{
while(sort_arr[i])
{
cout << i+1 << " ";
sort_arr[i]--;
}
}
return 0;
}

Remove and shift array c++

I want to locate a specific item from an array and then shift the array to remove that item. I have a list of integers {1, 2, 3, 4, 5, 6, 7, 8, 9} and want to remove the integer 2.
Currently I am getting an error: storage size of ‘new_ints’ isn’t known on the line:
int new_ints[];
Not sure what this means or how can I fix this?
Here is my code:
int main() {
int tmp = 2;
int valid_ints[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int new_ints[];
new_ints = stripList(tmp, valid_ints);
for (int i = 0; i < sizeof(new_ints); i++)
cout << new_ints[i] << endl;
return 0;
}
int *stripList (int tmp, int valid_ints[]){
for (int i = 0; i < sizeof(valid_ints); i++){
for (int j = tmp; j < sizeof(valid_ints); j++){
valid_ints[j] = valid_ints[j+1];
}
}
return valid_ints;
}
Like what Ben said, it is highly recommended to use an vector if you would like to resize your array to fit in new elements.
http://www.cplusplus.com/reference/vector/vector/vector/
Here's my example: (note alternatively you can use vector::erase to erase undesired elements)
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> valid_ints;
vector<int> new_ints;
int tmp = 2;
//read in elements
for(int i = 1; i <= 9; i++)
{
valid_ints.push_back(i);
}
//valid_ints will hold {1,2,3,4,5,6,7,8,9}
for(int i = 0; i < valid_ints.size(); i++)
{
//We will add an element to new_ints from valid_ints everytime the valid_ints[i] is NOT tmp. (or 2.)
if(valid_ints[i] != tmp)
{
new_ints.push_back(valid_ints[i]);
}
}
//Print out the new ints
for(int i = 0; i < new_ints.size(); i++)
{
cout << new_ints[i] << ' ';
}
return 0;
}
The resulting vector will be filled in this order:
{1}
{1,3} (skip 2!)
{1,3,4}
{1,3,4,5}
so on... until
{1,3,4,5,6,7,8,9}
So, the output would be:
1 3 4 5 6 7 8 9
In c++ size of an array must be known at compile time. Ie int new_ints[] is illegal. You will need to have a defined size ie new_ints[10]. (See here for more details) Or better yet, utilize the fantastic advantages of c++ and use a std::vector.