Reputation: 914
My goal is to split a vector into two parts: with unique values and with duplicates.
For example I have sorted vector myVec=(1,1,3,4,4,7,7,8,9,9)
which should be split into myVecDuplicates=(1,7,4,9)
and myVecUnique=(1,4,7,9,3,8).
So myVecDuplicates contains all values that have duplicates while myVecUnique contains all values but in a single embodiment.
The order does not matter. My idea was to use unique as it splits a vector into two parts. But I have a problem running my code.
vector<int> myVec(8)={1,1,3,4,4,7,8,9};
vector<int>::iterator firstDuplicate=unique(myVec.begin(),myVec.end());
vector<int> myVecDuplicate=myVec(firstDuplicate,myVec.end());\\here error accures that says ' no match for call to '(std::vector<int>) (std::vector<int>::iterator&, std::vector<int>::iterator)'
vector<int> myVecUnique=myVec(myVec.begin()+firstDuplicate-1,myVec.end());
After running this code I get an error that says (2nd line) 'no match for call to '(std::vector) (std::vector::iterator&, std::vector::iterator)'
Please help me to understand the source of error or maybe suggest some more elegant and fast way to solve my problem (without hash tables)!
Upvotes: 1
Views: 488
Reputation: 13934
Ahh..Too many edits in your question for anyone's liking. Just keep it simple by using map.
In C++, map comes really handy in storing the unique + sorted + respective_count values.
map<int, int> m;
for(auto &t : myVec){
m[t]++;
}
vector<int> myVecDuplicate, myVecUnique;
for(map<int, int>::iterator it = m.begin(); it != m.end(); it++){
if(it->second > 1) myVecDuplicate.push_back(it->first);
myVecUnique.push_back(it->first);
}
Edit:
maybe suggest some more elegant and fast way to solve my problem (without hash tables)!
and do
if (current_value == previous_value){
if(previous_value != previous_previous_value)
myVecDuplicate.push_back(current_value);
}
else{
myVecUnique.push_back(current_value);
}
To start, initialize previous_value = current_value - 1 and previous_previous_value as current_value - 2.
Upvotes: 1
Reputation: 44268
std::vector
has a constructor that accepts 2 iterators for range [first,second[ You cannot call constructor for existing object - it is already created, so your code
myVec(firstDuplicate,myVec.end());
actually tries to use myVec
as a functor, but std::vector
does not have operator()
hence the error.
you have 2 ways, pass 2 iterators to constructor directly:
vector<int> myVecDuplicate(firstDuplicate,myVec.end());
or use copy initialization with temporary vector:
vector<int> myVecDuplicate = vector<int>(firstDuplicate,myVec.end());
Same for the second vector:
vector<int> myVecUnique(myVec.begin(),firstDuplicate);
as pointed by Logman std::unique
does not seem to guarantee value of duplicates, so working solution can use std::set
instead (and you would not have to presort source vector):
std::set<int> iset;
vector<int> myVecUnique, myVecDuplicate;
for( auto val : myVec )
( iset.insert( val ).second ? myVecUnique : myVecDuplicate ).push_back( val );
Upvotes: 1
Reputation: 4189
O(n) complexity solution:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myVec = {1,1,3,4,4,7,7,8,9,9};
std::vector<int> myVecDuplicatec;
std::vector<int> myVecUnique;
for(int &x : myVec)
{
if(myVecUnique.size() == 0 || myVecUnique.back() != x)
myVecUnique.push_back(x);
else
myVecDuplicatec.push_back(x);
}
std::cout << "V = ";
for(int &x : myVec)
{
std::cout << x << ",";
}
std::cout << std::endl << "U = ";
for(int &x : myVecUnique)
{
std::cout << x << ",";
}
std::cout << std::endl << "D = ";
for(int &x : myVecDuplicatec)
{
std::cout << x << ",";
}
}
Upvotes: 1
Reputation: 29966
While this may be frowned upon (for not using standard algorithms and such), I would write some simple solution like this:
vector<int> myVec = {1,1,3,4,4,7,8,9};
unordered_set<int> duplicates;
unordered_set<int> unique;
for(int & v : myVec)
{
if(unique.count(v) > 0)
duplicates.insert(v);
else
unique.insert(v);
}
Upvotes: 1