Removing duplicates from an vector is giving unexpected results - c++

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;
}
}

Related

How would you remove a number from an unsorted vector using only .at(), .push_back(), .size(), and/or .resize()?

I'm new to C++ and I'm trying to write a void function that will delete a duplicate from a vector while preserving the order of the vector. I'm having trouble deleting the number from my vector using just .at(), .push_back(), .size(), and .resize(). How would I go about doing this?
This is what I have so far:
void RemoveDuplicates(std::vector<int>& vector, int vectorSize)
{
int i;
int j;
std::vector<int> tempVec;
for (i = 0; i < vector.size(); i++)
{
for (j = 1; j < vector.size(); j++)
{
if (vector.at(i) == vector.at(j))
{
tempVec.push_back(vector.at(i)); //Unduplicated Vector
}
}
}
}
If I were to put "1 2 3 3" in this it returns the tempVec as "2 3 3 3 3." The expected result was just "1 2 3." How would I go about fixing this so that it deduplicates the vector using just those vector manipulators?
Here's a simple approach, not very efficient but easy to understand
void RemoveDuplicates(std::vector<int>& vector)
{
std::vector<int> tempVec;
for (size_t i = 0; i < vector.size(); i++)
{
// look for vector[i] in remainder of vector
bool found = false;
for (size_t j = i + 1; j < vector.size(); j++)
{
if (vector.at(i) == vector.at(j))
{
found = true;
break;
}
}
// if not found it's not a duplicate
if (!found)
tempVec.push_back(vector.at(i));
}
vector = tempVec;
}
Building on your current idea, you can compare each value in vector with all the values in tempVec. If it's not found in tempVec, add it.
I'm using range based for-loops to simplify the looping:
#include <utility> // std::move
void RemoveDuplicates(std::vector<int>& vector) {
std::vector<int> tempVec;
for(int in : vector) { // `in` will be assigned one value at a time from vector
bool found = false; // set to `true` if the `in` value has already been seen
for(int out : tempVec) { // range based for-loop again
if(in == out) { // oups, duplicate
found = true; // set to true to avoid storing it
break; // and abort this inner loop
}
}
// only stored values not found:
if(not found) tempVec.push_back(in);
}
// move assign the result to `vector`:
vector = std::move(tempVec);
}
You do not need to pass the size of the vector. A vector knows its size(). Your code is not actually removing anything from vector.
Use the tools available to you.
You can use std::unique to remove duplicate adjacent elements. After sorting the vector this will remove all duplicates:
void RemoveDuplicates(std::vector<int>& vector)
{
std::sort(vector.begin(),vector.end());
auto it = std::unique(vector.begin(),vector.end());
vector = std::vector<int>(vector.begin(),it);
}
A std::set stores only unique elements, hence can be used too:
void RemoveDuplicates2(std::vector<int>& vector)
{
std::set<int> s{vector.begin(),vector.end()};
vector = std::vector<int>(s.begin(),s.end());
}
If you want to keep the initial ordering of the elements you can still use a std::set:
void RemoveDuplicates3(std::vector<int>& vector)
{
std::set<int> s;
std::vector<int> result;
for (const auto& e : vector) {
if (s.insert(e).second) { // not a duplicate
result.push_back(e);
}
}
vector = result;
}
And very similar, by searching the elements not in the set but in the result vector:
void RemoveDuplicates4(std::vector<int>& vector)
{
std::vector<int> result;
for (const auto& e : vector) {
if (std::find(result.begin(),result.end(),e) == result.end()){
result.push_back(e);
}
}
vector = result;
}
Live Demo
For starters the second parameter of the function is redundant and not used within the function. Remove it. The function should be declared like
void RemoveDuplicates( std::vector<int> &vector );
Also you forgot to change the original vector.
And it seems you mean inequality in the if condition
if (vector.at(i) != vector.at(j))
{
tempVec.push_back(vector.at(i)); //Unduplicated Vector
}
instead of the equality
if (vector.at(i) == vector.at(j))
{
tempVec.push_back(vector.at(i)); //Unduplicated Vector
}
Though in any case it is an incorrect logic within the inner for loop.
Your inner for loop is always start from 1
for (j = 1; j < vector.size(); j++)
So for this source vector { 1, 2, 3, 3 } the value 2 will be pushed once on the tempVec and for each element with the value 3 there will be pushed two values equal to 3 to tempVec.
Using your approach the function can look the following way.
void RemoveDuplicates( std::vector<int> &vector )
{
std::vector<int> tempVec;
for ( std::vector<int>::size_type i = 0; i < vector.size(); i++ )
{
std::vector<int>::size_type j = 0;
while ( j < tempVec.size() && vector.at( i ) != tempVec.at( j ) )
{
++j;
}
if ( j == tempVec.size() )
{
tempVec.push_back( vector.at( i ) );
}
}
std::swap( vector, tempVec );
}
Here is a demonstration program.
#include <iostream>
#include <vector>
void RemoveDuplicates( std::vector<int> &vector )
{
std::vector<int> tempVec;
for ( std::vector<int>::size_type i = 0; i < vector.size(); i++ )
{
std::vector<int>::size_type j = 0;
while ( j < tempVec.size() && vector.at( i ) != tempVec.at( j ) )
{
++j;
}
if ( j == tempVec.size() )
{
tempVec.push_back( vector.at( i ) );
}
}
std::swap( vector, tempVec );
}
int main()
{
std::vector<int> v = { 1, 2, 3, 3 };
std::cout << v.size() << ": ";
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
RemoveDuplicates( v );
std::cout << v.size() << ": ";
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
4: 1 2 3 3
3: 1 2 3
Resizing an array (including vectors) in-place and shifting items over by 1 each time a duplicate is found can be expensive.
If you can use a hash table based collection (i.e. unordered_set or unordered_map) to keep track of items already seen, you can have an O(N) based algorithm.
Aside from the std::unqiue solution already suggested, it's hard to beat this. std::unique is effectively the same thing.
void RemoveDuplicates(std::vector<int>& vec)
{
std::unordered_set<int> dupes;
std::vector<int> vecNew;
for (int x : vec)
{
if (dupes.insert(x).second)
{
vecNew.push_back(x);
}
}
vec = std::move(vecNew);
}

Deleting both an element and its duplicates in a Vector in C++

I've searched the Internet and known how to delete an element (with std::erase) and finding duplicates of an element to then delete it (vec.erase(std::unique(vec.begin(), vec.end()),vec.end());). But all methods only delete either an element or its duplicates.
I want to delete both.
For example, using this vector:
std::vector<int> vec = {2,3,1,5,2,2,5,1};
I want output to be:
{3}
My initial idea was:
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
int passedNumber = 0; //To tell amount of number not deleted (since not duplicated)
for (int i = 0; i != vec.size(); i = passedNumber) //This is not best practice, but I tried
{
if (vec[i] == vec[i+1])
{
int ctr = 1;
for(int j = i+1; j != vec.size(); j++)
{
if (vec[j] == vec[i]) ctr++;
else break;
}
vec.erase(vec.begin()+i, vec.begin()+i+ctr);
}
else passedNumber++;
}
}
And it worked. But this code is redundant and runs at O(n^2), so I'm trying to find other ways to solve the problem (maybe an STL function that I've never heard of, or just improve the code).
Something like this, perhaps:
void removeDuplicatesandElement(std::vector<int> &vec) {
if (vec.size() <= 1) return;
std::sort(vec.begin(), vec.end());
int cur_val = vec.front() - 1;
auto pred = [&](const int& val) {
if (val == cur_val) return true;
cur_val = val;
// Look ahead to the next element to see if it's a duplicate.
return &val != &vec.back() && (&val)[1] == val;
};
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
}
Demo
This relies heavily on the fact that std::vector is guaranteed to have contiguous storage. It won't work with any other container.
You can do it using STL maps as follows:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
void retainUniqueElements(vector<int> &A){
unordered_map<int, int> Cnt;
for(auto element:A) Cnt[element]++;
A.clear(); //removes all the elements of A
for(auto i:Cnt){
if(i.second == 1){ // that if the element occurs once
A.push_back(i.first); //then add it in our vector
}
}
}
int main() {
vector<int> vec = {2,3,1,5,2,2,5,1};
retainUniqueElements(vec);
for(auto i:vec){
cout << i << " ";
}
cout << "\n";
return 0;
}
Output:
3
Time Complexity of the above approach: O(n)
Space Complexity of the above approach: O(n)
From what you have searched, we can look in the vector for duplicated values, then use the Erase–remove idiom to clean up the vector.
#include <vector>
#include <algorithm>
#include <iostream>
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
if (vec.size() < 2)
return;
for (int i = 0; i < vec.size() - 1;)
{
// This is for the case we emptied our vector
if (vec.size() < 2)
return;
// This heavily relies on the fact that this vector is sorted
if (vec[i] == vec[i + 1])
vec.erase(std::remove(vec.begin(), vec.end(), (int)vec[i]), vec.end());
else
i += 1;
}
// Since all duplicates are removed, the remaining elements in the vector are unique, thus the size of the vector
// But we are not returning anything or any reference, so I'm just gonna leave this here
// return vec.size()
}
int main()
{
std::vector<int> vec = {2, 3, 1, 5, 2, 2, 5, 1};
removeDuplicatesandElement(vec);
for (auto i : vec)
{
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
Output: 3
Time complexity: O(n)

give how many numbers in a vector that are less than itself

i have to find how many other numbers are less than nums[i] and return them in another vector, for example [6,5,4,8] nums[0] = 6 so there is two numbers less than 6. so 2 would be pushed to the other vector. i am not getting 3 when it comes to checking the last element
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> nums2;
for(int i =0; i< nums.size(); ++i){
int max = nums[i];
int count = 0;
for(int j =0; j < nums.size(); ++j){
if(nums[j] < max && j!=0)
count++;
else
continue;
}
nums2.push_back(count);
}
return nums2;
}
};
You exclude the first element when counting in the condition:
if(nums[j] < max && j!=0)
// ^^ ---- remove this
There are algorithms that do want you need. std::transform transforms one range of values to another one and count_if counts how often a predicate returns true for a given range:
#include <vector>
#include <iostream>
#include <algorithm>
std::vector<size_t> count_if_smaller(const std::vector<int>& v) {
std::vector<size_t> result(v.size());
std::transform(v.begin(),v.end(),result.begin(),
[&](int x){
return std::count_if(v.begin(),v.end(),[&](int y){
return y < x;
});
} );
return result;
}
int main() {
std::vector<int> v{6,5,4,8};
auto r = count_if_smaller(v);
for (auto e : r) std::cout << e << " ";
}
One advantage of using algorithms is that you need not bother about indices of single elements. Introducing the same bug as in your code would be more difficult in the above. In other words, using algorithms is less error prone. Consider to use them when you can.
PS: Your current approach has complexity O(N^2). If you sort the input vector you could get O(N log N) easily.

Repeating elements in vector

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;
}

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]);
}
}
}