How to find unique values in a vector c++ - c++

I am trying to solve a coding problem where I am to check and see if a vector has unique values and if it does then return true else false.
So Far I thought of using a nested loops where you would compare the first to the last, but I am wanted to know if C++ has anything else then doing a o(n^2) type iteration. I saw that c++ has a unique function, but that would delete the unique value.
Example 1:
Input: nums = [1,2,3,1]
Output: true
Example 2:
Input: nums = [1,2,3,4]
Output: false

std::unique checks for consecutive duplicates and moves them to the end of the range. It does not remove them from the vector. Anyhow you can make a copy. It also returns an iterator to the end of the range of unique values (that are now in the front of the vector):
#include <iostream>
#include <vector>
#include <algorithm>
bool only_unique(std::vector<int> v) {
std::sort(v.begin(),v.end());
return std::unique(v.begin(),v.end()) == v.end();
}
int main(){
std::cout << only_unique({1,2,3,1});
std::cout << only_unique({1,2,3,4});
}
If you don't want to use the additional memory you can change the argument to a reference. Currently, only_unique leaves the parameter unmodified. Even if the vector is passed by reference the duplicates will still be present (just at a different position). This has O(n log n) complexity.

you need to create "set" structure,
it makes it possible to insert values from vector and does not insert the duplicates,
so you can check if the size of the set and the vector match or not.
set<int> st;
for (auto i : nums)
st.insert(i);
return st.size() == nums.size();

Related

unordered_map elements disappeared after [] operation in c++

The behavior that unodered_map elements disappeared unexpectedly in the following C++ code confused me a whole lot. In the first for loop I stored the remainder of each element in time moduled by 60 and its count in unordered_map<int, int> m, in the second for loop, I printed the content in m, so far everything seems working right.
cout as following
0:1
39:1
23:1
18:1
44:1
59:1
12:1
38:1
56:2
17:1
37:1
24:1
58:1
However in the third for loop, it only printed part of elements in m,
0:1
39:1
58:1
0:1
it seems many elements in m were erased by n += m[remainder]*m[60-remainder]; operation. I was so confused by this behavior, could you please understand what is going here? Really so confused.
#include <iostream>
#include<unordered_map>
#include<vector>
using namespace std;
int main() {
vector<int> time ({418,204,77,278,239,457,284,263,372,279,476,416,360,18});
int n =0;
unordered_map<int,int> m; // <remiander,cnt>
for (auto t:time)
m[t%60]++;
for (auto [remainder,cnt]:m)
cout<<remainder<<":"<<cnt<<endl;
cout<<endl;
for (auto [remainder,cnt]:m){
cout<<remainder<<":"<<cnt<<endl;
if (remainder==0 || remainder==30)
n += cnt*(cnt-1)/2;
else
n += m[remainder]*m[60-remainder];
}
}
The third loop uses the [] operator inside the loop.
for (auto [remainder,cnt]:m){
// ...
n += m[remainder]*m[60-remainder];
unordered_map's [] invalidates all existing iterators if it results in a rehash. This includes the implicit iterators employed during range iteration.
As shown, m[remainder] cannot cause a rehash because it can only access an existing value in the unordered map, but this is not true for m[60-remainder], resulting in undefined behavior.
You just need to remove this usage of the [] operator and replace it with the equivalent find() (and, of course, correctly handling the end() value if it gets returned).

Can we get an iterator that filters a vector from a predicate in C++?

Is it possible to get an iterator over a vector that filters some element with a predicate, i.e. showing a view of the vector?
I think remove_if does something similar but I have not found whether I can use it as I want to or not.
Something like:
auto it = filter(vec.begin(), vec.end(), predicate);
// I can reuse the iterator like:
for (auto i = it; i != vec.end(); i++)
// ...
Edit: (A bit more context to get the best answer) I am doing a lot of queries in an sqlite database of log data in order to print a report.
The performances are not good at the moment because of the number of request needed. I believe querying once the database and storing the result in a vector of smart pointers (unique_ptr if possible), then querying the vector with pure C++ may be faster.
Using copy_if is a good way to do the queries, but I don't need to copy everything and it might cost too much at the end (not sure about that), I should have mentioned than the data are immutable in my case.
As #Jarod42 mentioned in the comments one solution would be using ranges:
#include <algorithm>
#include <iostream>
#include <vector>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
int main()
{
std::vector<int> numbers = { 1, 2, 3 ,4, 5 };
auto predicate = [](int& n){ return n % 2 == 0; };
auto evenNumbers = numbers | ranges::view::filter(predicate);
auto result = numbers | ranges::view::filter(predicate)
| ranges::view::transform([](int n) { return n * 2; });
for (int n : evenNumbers)
{
std::cout << n << ' ';
}
std::cout << '\n';
for (int n : result)
{
std::cout << n << ' ';
}
}
evenNumbers is a range view adapter which sticks to the numbers range and changes the way it iterates.
result is a ranges of numbers that have been filtered on the predicate and then have been applied a funciton.
see the compile at compiler-explorer
credit: fluentcpp
Your question
Can we get an iterator that filters a vector from a predicate in C++?
in the sense you are asked it, can only be answered with: No. At the moment not (C++17). As per your requirement the iterator then would have to store the predicate and checking that for each modification of the position or for all dereferencing stuff. I.e before any dereferencing, the predicate would need to be checked. Because other code could modifiy your std::vector. The the iterator would need to check the predicate all the time. Also standard functionality like begin, end, distance would be rather complicated.
So you could create your own iterator by deriving from an existing iterator. Store the predicate and overload most of the functions to take care of the predicate. Very, very complicated, much work and maybe not, what you want to have. This would be the only way to get exact your requested functionality.
For work arounds, there are are many other possible solutions. Peolple will show you here.
But if I read your statement
"showing a view of the vector"
then life becomes easier. You can easily create a view of a vector by copying it conditionally with std::copy_if, as oblivion has written. That is in my opinion the best answer. It is none destructive. But it is a snapshot and not the original data. So, it is read only. And, it does not take into account changes to the original std::vector after the snapshot has been taken.
The second option, a combination of std::remove_if and std::erase, will destroy the original data. Or better said, it will invalidate the filtered out data. You could also std::copy_if the unwanted data to a backup area, std::remove_if them, and at the end add them again to the vector.
All these methods are critical, if the original data will be modified.
Maybe for you the standard std::copy_if is best to create a view. You would then return an iterator of copy and work with that.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> testVector{ 1,2,3,4,5,6,7 }; // Test data
std::vector<int> testVectorView{}; // The view
// Create predicate
auto predForEvenNumbers = [](const int& i) -> bool { return (i % 2 == 0); };
// And filter. Take a snapshot
std::copy_if(testVector.begin(), testVector.end(), std::back_inserter(testVectorView), predForEvenNumbers);
// Show example result
std::vector<int>::iterator iter = testVectorView.begin();
std::cout << *iter << '\n';
return 0;
}
Please note. For big std::vectors, it will become a very expensive solution . . .

all_of function to check condition in all elements of part of an array

The following code checks if all elements in the declared array are odd numbers.
#include "stdafx.h"
#include <iostream> // std::cout
#include <algorithm> // std::all_of
#include <array> // std::array
int main () {
std::array<int,8> foo = {3,5,7,11,13,17,19,23};
if ( std::all_of(foo.begin(), foo.end(), [](int i){return i%2;}) )
std::cout << "All the elements are odd numbers.\n";
return 0;
}
(Sample taken from http://www.cplusplus.com/reference/algorithm/all_of)
I would like to check if all elements in the declared array starting from foo[2] are odd numbers.
Replacing foo.begin() with foo[2] does not work. I've tried many other things to make this work, all very basic (very basic C++ user here), without success. I do not want to resize the array for achieving this.
Ultimately what I'm looking for is having a loop where a condition is checked for on every element of part of an array, just as the for loop checks for a condition on any element of part of an array. This is relatively easy to achieve in R, and I'm hoping it may be equally easy to achieve in C++.
You can't use an iterator and an element here, they don't represent a range. In a more general sense, even attempting to use a pointer to an element and an iterator would not be well defined for all implementations of any given container either.
You should use std::next(it.begin(), 2) to increment to the begin() iterator to the foo[2] element and then you can iterate over the range with the two iterators.
std::all_of(std::next(foo.begin(), 2), foo.end(),
[](int i){/*...*/})
std::next() is more general and caters for iterators other than just random access iterators (e.g. for the alternate it.begin() + 2); but will still be performant for the type of iterator passed to it.

Which order is used to stack or heap variable creation [duplicate]

This question already has an answer here:
How do I erase elements from STL containers?
(1 answer)
Closed 8 years ago.
I've this code:
#include <algorithm>
#include <iostream>
#include <list>
using namespace std;
struct P
{
bool operator()(const int &n) const
{
return n % 3 == 0;
}
};
int main()
{
std::list<int> l({ 5, 2, 6, 1, 13, 9, 19 });
std::cout << l.size();
std::remove_if(l.begin(), l.end(), P());
std::cout << l.size() << std::endl;
return 0;
}
prints out "77". I expected it would have printed out "75", because the operator () of the P struct, returns true when its argument has not remainder of the division by 3. And that's the case for '6' and '9' (two elements out of seven).
Am I missing something ?
thanks.
To quote from http://www.cplusplus.com/reference/algorithm/remove_if/
The function cannot alter the properties of the object containing the range of elements (i.e., it cannot alter the size of an array or a container): The removal is done by replacing the elements for which pred returns true by the next element for which it does not, and signaling the new size of the shortened range by returning an iterator to the element that should be considered its new past-the-end element.
In other words, it rearranges the elements in the given range so that all the non-removed ones are at the beginning, then returns an iterator just past the end of the non-removed part. But it can't delete any elements, because it doesn't know anything about the underlying container.
Is it possible std::remove_if returns the resulting list?
remove/remove_if only reorders a sequence, it doesn't modify it. Iterators have no access to or knowledge of the container from which they come. You need to pass the result to a suitable erase container member:
l.erase(std::remove_if(l.begin(), l.end(), P()), l.end());
Don't forget the second l.end() so that you get the two-iterator overload of erase that erases a whole range. If you forget it, you end up with the one-iterator overload that only erases a single element.

C++ Standard Library approach to removing one of a pair of items in a list that satisfy a criterion

Imagine you have an std::list with a set of values in it. For demonstration's sake, we'll say it's just std::list<int>, but in my case they're actually 2D points. Anyway, I want to remove one of a pair of ints (or points) which satisfy some sort of distance criterion. My question is how to approach this as an iteration that doesn't do more than O(N^2) operations.
Example
Source is a list of ints containing:
{ 16, 2, 5, 10, 15, 1, 20 }
If I gave this a distance criterion of 1 (i.e. no item in the list should be within 1 of any other), I'd like to produce the following output:
{ 16, 2, 5, 10, 20 } if I iterated forward or
{ 20, 1, 15, 10, 5 } if I iterated backward
I feel that there must be some awesome way to do this, but I'm stuck with this double loop of iterators and trying to erase items while iterating through the list.
Make a map of "regions", basically, a std::map<coordinates/len, std::vector<point>>.
Add each point to it's region, and each of the 8 neighboring regions O(N*logN). Run the "nieve" algorithm on each of these smaller lists (technically O(N^2) unless theres a maximum density, then it becomes O(N*density)). Finally: On your origional list, iterate through each point, and if it has been removed from any of the 8 mini-lists it was put in, remove it from the list. O(n)
With no limit on density, this is O(N^2), and slow. But this gets faster and faster the more spread out the points are. If the points are somewhat evenly distributed in a known boundary, you can switch to a two dimensional array, making this significantly faster, and if there's a constant limit to the density, that technically makes this a O(N) algorithm.
That is how you sort a list of two variables by the way. The grid/map/2dvector thing.
[EDIT] You mentioned you were having trouble with the "nieve" method too, so here's that:
template<class iterator, class criterion>
iterator RemoveCriterion(iterator begin, iterator end, criterion criter) {
iterator actend = end;
for(iterator L=begin; L != actend; ++L) {
iterator R(L);
for(++R; R != actend;) {
if (criter(*L, *R) {
iterator N(R);
std::rotate(R, ++N, actend);
--actend;
} else
++R;
}
}
return actend;
}
This should work on linked lists, vectors, and similar containers, and works in reverse. Unfortunately, it's kinda slow due to not taking into account the properties of linked lists. It's possible to make much faster versions that only work on linked lists in a specific direction. Note that the return value is important, like with the other mutating algorithms. It can only alter contents of the container, not the container itself, so you'll have to erase all elements after the return value when it finishes.
Cubbi had the best answer, though he deleted it for some reason:
Sounds like it's a sorted list, in which case std::unique will do the job of removing the second element of each pair:
#include <list>
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
std::list<int> data = {1,2,5,10,15,16,20};
std::unique_copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int n, int m){return abs(n-m)<=1;});
std::cout << '\n';
}
demo: https://ideone.com/OnGxk
That trivially extends to other types -- either by changing int to something else, or by defining a template:
template<typename T> void remove_close(std::list<T> &data, int distance)
{
std::unique_copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
[distance](T n, T m){return abs(n-m)<=distance;});
return data;
}
Which will work for any type that defines operator - and abs to allow finding a distance between two objects.
As a mathematician I am pretty sure there is no 'awesome' way to approaching this problem for an unsorted list. It seems to me that it is a logical necessity to check the criterion for any one element against all previous elements selected in order to determine whether insertion is viable or not. There may be a number of ways to optimize this, depending on the size of the list and the criterion.
Perhaps you could maintain a bitset based on the criterion. E.g. suppose abs(n-m)<1) is the criterion. Suppose the first element is of size 5. This is carried over into the new list. So flip bitset[5] to 1. Then, when you encounter an element of size 6, say, you need only test
!( bitset[5] | bitset[6] | bitset[7])
This would ensure no element is within magnitude 1 of the resulting list. This idea may be difficult to extend for more complicated(non discrete) criterions however.
What about:
struct IsNeighbour : public std::binary_function<int,int,bool>
{
IsNeighbour(int dist)
: distance(dist) {}
bool operator()(int a, int b) const
{ return abs(a-b) <= distance; }
int distance;
};
std::list<int>::iterator iter = lst.begin();
while(iter != lst.end())
{
iter = std::adjacent_find(iter, lst.end(), IsNeighbour(some_distance)));
if(iter != lst.end())
iter = lst.erase(iter);
}
This should have O(n). It searches for the first pair of neighbours (which are at maximum some_distance away from each other) and removes the first of this pair. This is repeated (starting from the found item and not from the beginning, of course) until no pairs are found anymore.
EDIT: Oh sorry, you said any other and not just its next element. In this case the above algorithm only works for a sorted list. So you should sort it first, if neccessary.
You can also use std::unique instead of this custom loop above:
lst.erase(std::unique(lst.begin(), lst.end(), IsNeighbour(some_distance), lst.end());
but this removes the second item of each equal pair, and not the first, so you may have to reverse the iteration direction if this matters.
For 2D points instead of ints (1D points) it is not that easy, as you cannot just sort them by their euclidean distance. So if your real problem is to do it on 2D points, you might rephrase the question to point that out more clearly and remove the oversimplified int example.
I think this will work, as long as you don't mind making copies of the data, but if it's just a pair of integer/floats, that should be pretty low-cost. You're making n^2 comparisons, but you're using std::algorithm and can declare the input vector const.
//calculates the distance between two points and returns true if said distance is
//under its threshold
bool isTooClose(const Point& lhs, const Point& rhs, int threshold = 1);
vector<Point>& vec; //the original vector, passed in
vector<Point>& out; //the output vector, returned however you like
for(b = vec.begin(), e = vec.end(); b != e; b++) {
Point& candidate = *b;
if(find_if(out.begin(),
out.end(),
bind1st(isTooClose, candidate)) == out.end())
{//we didn't find anyone too close to us in the output vector. Let's add!
out.push_back(candidate);
}
}
std::list<>.erase(remove_if(...)) using functors
http://en.wikipedia.org/wiki/Erase-remove_idiom
Update(added code):
struct IsNeighbour : public std::unary_function<int,bool>
{
IsNeighbour(int dist)
: m_distance(dist), m_old_value(0){}
bool operator()(int a)
{
bool result = abs(a-m_old_value) <= m_distance;
m_old_value = a;
return result;
}
int m_distance;
int m_old_value;
};
main function...
std::list<int> data = {1,2,5,10,15,16,20};
data.erase(std::remove_if(data.begin(), data.end(), IsNeighbour(1)), data.end());