Repeating elements in vector - c++

I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}

Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.

It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}

Related

Removing duplicates from an vector is giving unexpected results

Given a vector of integers, iterate through the vector and check whether there are more than one of the same number. In that case, remove them so that only a single index of the vector contains that number. Here are a few examples:
vector<int> arr {1,1,1,1}
When arr is printed out the result should be 1.
vector<int> arr {1,2,1,2}
When arr is printed out the result should be 1,2.
vector<int> arr {1,3,2}
When arr is printed out the result should be 1,3,2.
I know there are many solutions regarding this, but I want to solve it using my method. The solutions I've looked at use a lot of built-in functions, which I don't want to get too comfortable with as a beginner. I want to practice my problem-solving skills.
This is my code:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> arr {1,1,1,1,2,1,1,1,1,1};
for (int i {}; i < arr.size(); ++i)
{
int counter {};
for (int j {}; j < arr.size(); ++j)
{
if (arr.at(i) == arr.at(j))
{
counter++;
if (counter > 1)
arr.erase(arr.begin()+j);
}
}
}
//Prints out the vector arr
for (auto value : arr)
{
cout << value << endl;
}
return 0;
}
The thing is that it works for the most part, except a few cases which have me confused.
For instance:
vector<int> arr {1,1,1,1,2,1,1,1,1,1}
When arr is printed out the result is 1,2,1 instead of 1,2.
However, in this case:
vector<int> arr {1,1,1,1,2,1,1,1}
When arr is printed out the result is 1,2.
It seems to work in the vast majority of cases, but when a number repeats itself a lot of times in the vector, it seems to not work, and I can't seem to find a reason for this.
I am now asking you to firstly tell me the cause of the problem, and then to give me guidance on how I should tackle this problem using my solution.
The machine I'm using has a pre C++11 compiler so this is an answer in the old fashioned C++. The easy way around this is to erase backwards. That way you don't have to worry about the size. Also, instead of using a for loop, which may be optimised, use a while loop.
#include <iostream>
#include <vector>
int main()
{
int dummy[] = {1,1,1,1,2,1,1,1,1,1};
std::vector<int> arr(dummy, dummy + sizeof(dummy)/sizeof(dummy[0]));
size_t ii = 0;
while (ii < arr.size())
{
// Save the value for a little efficiency
int value = arr[ii];
// Go through backwards only as far as ii.
for (size_t jj = arr.size() - 1; jj > ii; --jj)
{
if (value == arr[jj])
arr.erase(arr.begin() + jj);
}
++ii;
}
//Prints out the vector arr
for (size_t ii = 0; ii < arr.size(); ++ii)
{
std::cout << arr[ii] << std::endl;
}
return 0;
}
As mentioned in the comments, when you erase a found duplicate (at index j), you are potentially modifying the position of the element at index i.
So, after you have called arr.erase(arr.begin() + j), you need to adjust i accordingly, if it was referring to an element that occurs after the removed element.
Here's a "quick fix" for your function:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> arr{ 1,1,1,1,2,1,1,1,1,1 };
for (size_t i{}; i < arr.size(); ++i) {
int counter{};
for (size_t j{}; j < arr.size(); ++j) {
if (arr.at(i) == arr.at(j)) {
counter++;
if (counter > 1) {
arr.erase(arr.begin() + j);
if (i >= j) --i; // Adjust "i" if it's after the erased element.
}
}
}
}
//Prints out the vector arr
for (auto value : arr) {
std::cout << value << std::endl;
}
return 0;
}
As also mentioned in the comments, there are other ways of making the function more efficient; however, you have stated that you want to "practice your own problem-solving skills" (which is highly commendable), so I shall stick to offering a fix for your immediate issue.
This inner for loop is incorrect
int counter {};
for (int j {}; j < arr.size(); ++j)
{
if (arr.at(i) == arr.at(j))
{
counter++;
if (counter > 1)
arr.erase(arr.begin()+j);
}
}
If an element was removed the index j shall not be increased. Otherwise the next element after deleted will be bypassed because all elements after the deleted element in the vector are moved one position left.
Using the variable counter is redundant. Just start the inner loop with j = i + 1.
Using your approach the program can look the following way
#include <iostream>
#include <vector>
int main()
{
std::vector<int> arr{ 1,1,1,1,2,1,1,1,1,1 };
for ( decltype( arr )::size_type i = 0; i < arr.size(); ++i)
{
for ( decltype( arr )::size_type j = i + 1; j < arr.size(); )
{
if (arr.at( i ) == arr.at( j ))
{
arr.erase( arr.begin() + j );
}
else
{
j++;
}
}
}
//Prints out the vector arr
for (auto value : arr)
{
std::cout << value << std::endl;
}
}
The program output is
1
2
This approach when each duplicated element is deleted separately is inefficient. It is better to use the so called erase-remove idiom.
Here is a demonstration program.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> arr{ 1,1,1,1,2,1,1,1,1,1 };
for (auto first = std::begin( arr ); first != std::end( arr ); ++first)
{
arr.erase( std::remove( std::next( first ), std::end( arr ), *first ), std::end( arr ) );
}
//Prints out the vector arr
for (auto value : arr)
{
std::cout << value << std::endl;
}
}

Minimum Swaps 2 - minimum number of swaps required to sort a vector in ascending order

I'm doing a fairly easy HackerRank test which asks the user to write a function which returns the minimum number of swaps needed to sort an unordered vector in ascending order, e.g.
Start: 1, 2, 5, 4, 3
End: 1, 2, 3, 4, 5
Minimum number of swaps: 1
I've written a function which works on 13/14 test cases, but is too slow for the final case.
#include<iostream>
#include<vector>
using namespace std;
int mimumumSwaps(vector<int> arr) {
int p = 0; // Represents the (index + 1) of arr, e.g. 1, 2, ..., arr.size() + 1
int swaps = 0;
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i) {
p++;
if (*i == p) // Element is in the correct place
continue;
else{ // Iterate through the rest of arr until the correct element is found
for (vector<int>::iterator j = arr.begin() + p - 1; j != arr.end(); ++j) {
if (*j == p) {
// Swap the elements
double temp = *j;
*j = *i;
*i = temp;
swaps++;
break;
}
}
}
}
return swaps;
}
int main()
{
vector<int> arr = { 1, 2, 5, 4, 3 };
cout << mimumumSwaps(arr);
}
How would I speed this up further?
Are there any functions I could import which could speed up processes for me?
Is there a way to do this without actually swapping any elements and simply working out the min. swaps which I imagine would speed up the process time?
All permutations can be broken down into cyclic subsets. Find said subsets.
Rotating a subset of K elements by 1 takes K-1 swaps.
Walk array until you find an element out of place. Walk that cycle until it completes. Advance, skipping elements that you've put into a cycle already. Sum (size-1) for each cycle.
To skip, maintain an ordered or unordered set of unexamined items, and fast remove as you examine them.
I think that gives optimal swap count in O(n lg n) or so.
#include <bits/stdc++.h>
#include <vector>
#include <algorithm>
using namespace std;
int minimumSwaps(vector<int> arr)
{
int i,c,j,k,l;
j=c=0;
l=k=arr.size();
while (j<k)
{
i=0;
while (i<l)
{
if (arr[i]!=i+1)
{
swap(arr[i],arr[arr[i]-1]);
c++;
}
i++;
}
k=k/2;
j++;
}
return c;
}
int main()
{
int n,q;
cin >> n;
vector<int> arr;
for (int i = 0; i < n; i++)
{
cin>>q;
arr.push_back(q);
}
int res = minimumSwaps(arr);
cout << res << "\n";
return 0;
}

How do I demonstrate the following algorithm has O(nlogn) time complexity

It's an algorithm that finds the mininum number of descending rows and the rows themselves of an array in O(nlogn) time complexity . Another part of the exercise is to use these descending rows to implement Patience Sort, which also has to be O(nlogn) (that is from the c = 1 part). What I don't get is where the logn part comes from in both cases.
#include <iostream>
#include <fstream>
#include <list>
using namespace std;
ifstream f("data.in");
int main()
{
int n, v[100];
f >> n;
for (int i = 0; i < n; i++)
f >> v[i];
list<int> aux;
aux.push_back(v[0]);
list<list<int> > rows;
rows.push_back(aux);
for (int i = 1; i < n; i++)
{
int selected = 0;
for (list<list<int> >::iterator it = rows.begin(); it != rows.end(); it++)
{
if (it->back() > v[i])
{
it->push_back(v[i]);
selected = 1;
break;
}
}
if (!selected)
{
list<int> aux;
aux.push_back(v[i]);
rows.push_back(aux);
}
}
for (list<list<int> >::iterator it = rows.begin(); it != rows.end(); it++)
{
for (list<int>:: iterator it2 = it->begin(); it2 != it->end(); it2++)
cout << *it2 << " ";
cout << endl;
}
int c = 1;
if (c == 1)
{
int s[100];
for (int i = 0; i < n; i++)
{
list<list<int> >::iterator it = rows.begin();
int minim = it->back();
it++;
while (it != rows.end())
{
if (!it->empty())
if (it->back() < minim)
minim = it->back();
it++;
}
it = rows.begin();
while (it != rows.end())
{
if (it->back() == minim)
{
it->pop_back();
if (it->empty())
rows.erase(it);
break;
}
it++;
}
s[i] = minim;
}
for (int i = 0; i < n; i++)
cout << s[i] << " ";
}
}
Your outer loops process each piece of input data so the growth is linear, e.g. O(n). Your inner loops only process a smaller subset of the full input data and the growth is logarithmic, e.g. O(log n). Hence the growth is linearithmic, e.g. O(nlogn). If the inner loop processed each piece of input data, the growth would be quadratic, e.g. O(n^2)
A good explanation can be found here:
What does O(log n) mean exactly?
EDIT: My mistake. I agree with the comments under the original post that the growth of the program seems to be O(n^2). I was a little bit quick in the turns. On a quick peek, it looked to me initially that the innerloops were executed log n times. But it looks like that is not the case for the inner loops in the second n iterations. However, as far as I understand the first innerloop seems to me to be executed log n times (so the order of the growth in sorting the rows is O(nlogn)), but maybe I am mistaken.

Splitting an array at a given value

Hello I am trying to split an array any time there is a negative value (excluding the negative value) and am a bit stuck at the moment. I tried an approach as seen in my code but I am not getting the desired output.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
string line;
string filename;
int n,length;
std::vector<int>arr1;
fstream file("t1.txt");
if(file.is_open())
{
while(file >> n)
arr1.push_back(n);
for(int i =0; i < (int)arr1.size(); i++)
cout << arr1.at(i);
}
cout << endl;
int* arr2 = &arr1[0];
int arr3[arr1.size()/2];
int arr4[arr1.size()/2];
for(int i = 0; i < arr1.size(); i++)
{
cout << arr2[i];
}
for (int i =0; i < arr1.size(); i++)
{
if(i == -1)
break;
else
arr3[i] = arr2[i];
}
return 0;
}
The main problem is here:
int arr3[arr1.size()/2];
int arr4[arr1.size()/2];
This doesn't compile, and can be replaced with
std::vector<int> arr3; arr3.reserve(arr1.size() / 2);
std::vector<int> arr4; arr4.reserve(arr1.size() / 2);
I've added the "reserve" function so that the program doesn't have to allocate memory over and over in the loop.
Next, you are checking i in your loop, and your i loops from 0 to arr1.size() (which is unsigned so can't be negative) therefore i will never be negative.
What you really wanna check is what is in the arr1 vector at "i" position, and you can do so with the [] operator like
for (int i =0; i < arr1.size(); i++)
{
if (arr1[i] >= 0) //if the value is positive, we push it inside our arr3 vector
arr3.push_back(arr1[i]);
else
{
i++; //skip negative value
//
while (i < arr1.size())
{
if (arr1[i] > 0)
arr4.push_back(arr1[i]);
i++;
}
//
//or
//insert all the elemenents we haven't processed yet in the arr4 vector
//this code assumes those elements are positive values
//arr4.insert(arr4.begin(), arr1.begin() + i, arr1.end());
//break;
}
}
Of course this could be done in a different way, like instead of creating 2 vectors, you could just use the one you have generated already.
Hope this helps.
There are several problems in your code
you should not access the vector's data this way unless you really need to
you prepare arrays with predefined size without knowing where to expect the negative values
you do not assign anything to your array 4
you check the index for being negative, not the value
according to your text there could be several negative values leading to multiple result-arrays. You seem to be prepared for only two.
Here is some code that actually splits when encountering negative values:
std::vector<vector<int> > splitted;
for (int i = 0; i < arr1.size(); ++i)
{
if (i ==0 or arr1[i] < 0)
splitted.push_back(std::vector<int>());
if (arr1[i] >= 0)
splitted.back().push_back(arr1[i]);
}
Testing it:
for (int i = 0; i < splitted.size(); ++i)
{
for (int k = 0; k < splitted[i].size(); ++k)
{
std::cout << splitted[i][k];
}
if (splitted[i].empty())
std::cout << "(emtpy)";
std::cout << '\n';
}
Using the following test input
1 2 3 -1 1 -1 -1
You get the following output:
123
1
(emtpy)
(emtpy)

How do I delete a particular element in an integer array given an if condition?

I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}