using find() to find elements in a vector - c++

I have a vector which stores some integers. In this vector, there can be all numbers except 10, 12, 31 cannot appear together or in pairs i.e., 10 and 12, 10 and 31, 12 and 31, 10 12 and 31 are invalid. I have come up with the following approach:
int main(){
int a[] = {10,2,31}; //can be of any size
vector<int> v(a, a+3);
short cnt = 0;
if(find(v.begin(), v.end(), 10) != v.end())
++cnt;
if(find(v.begin(), v.end(), 12) != v.end())
++cnt;
if(find(v.begin(), v.end(), 31) != v.end())
++cnt;
if(cnt > 1)
cout<<"Invalid options";
else
cout<<"Valid options";
return EXIT_SUCCESS;
}
which works. Is there a better way to do this? Especially, since the vector can contain any number of elements, can there be any downside?

How about count:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count ( ForwardIterator first, ForwardIterator last, const T& value );
(see http://www.cplusplus.com/reference/algorithm/count/)
or, count_if (which only traverses the list once):
template <class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if ( ForwardIterator first, ForwardIterator last, Predicate pred );
which requires the minor extra work of a predicate, something like:
bool checkvalues(int i) {
return (i==10 || i==12 || i==31);
}
or you could be more clever and make a class with operator() if you want to specify the possible values at runtime.
(see http://www.cplusplus.com/reference/algorithm/count_if/)
Is the issue about invalid pairs and triples a red herring?

If you sort them then you can use std::binary_search, which will run faster when the number of elements in the vector is large (would need to be very large though to have any noticeable difference).
std::sort(v.begin(), v.end());
if (std::binary_search(v.begin(), v.end(), 10)) cnt++;
if (std::binary_search(v.begin(), v.end(), 12)) cnt++;
if (std::binary_search(v.begin(), v.end(), 31)) cnt++;

You could try a set_intersection, as in the example below:
int a[] = {10,2,12}; //can be of any size
int b[] = {10,12,31}; // set we are interested in, sorted already to save a sort
sort (a, a+3);
vector<int> dest(sizeof(a)/sizeof(a[0])); // matching items will go here
vector<int>::iterator it;
it = set_intersection (a, a+3, b, b+3, dest.begin());
if (distance(dest.begin(), it) > 1) // oops means more than one item has matched...

You should always use brackets around if statements even if the statement is only 1 line long.
if(find(v.begin(), v.end(), 31) != v.end())
++cnt;
Reading your code can get very confusing without the brackets. And if you want to add another statement to that if condition, you could introduce a very hard to debug error.

Related

I need a std function which checks how many elements occur exactly once in vector

Is there any STL function which does this?
For vector:
4 4 5 5 6 7
The expected output should be 2,because of one 6 and 7
Would you be kind to help me count them classic if there is no STL function?
I don't think there is an algorithm for that in STL. You can copy into a multimap or use a map of frequencies as suggested, but it does extra work that's not necessary because your array happens to be sorted. Here is a simple algorithm that counts the number of singular elements i.e. elements that appear only once in a sorted sequence.
int previous = v.front();
int current_count = 0;
int total_singular = 0;
for(auto n : v) {
if(previous == n) // check if same as last iteration
current_count++; // count the elements equal to current value
else {
if(current_count == 1) // count only those that have one copy for total
total_singular++;
previous = n;
current_count = 1; // reset counter, because current changed
}
}
if(current_count == 1) // check the last number
total_singular++;
You could also use count_if with a stateful lambda, but I don't think it'll make the algorithm any simpler.
If performance and memory doesn't matter to you, use std::map (or unordered version) for this task:
size_t count(const std::vector<int>& vec){
std::map<int,unsigned int> occurenceMap;
for (auto i : vec){
occurenceMap[i]++;
}
size_t count = 0U;
for (const auto& pair : occurenceMap){
if (pair.second == 1U){
count++;
}
}
return count;
}
with templates, it can be generalize to any container type and any containee type.
Use std::unique to count the unique entries(ct_u) and then user vector count on the original one (ct_o). Difference ct_o-ct_u would give the answer.
P.S.: this will only work if the identical entries are together in the original vector. If not, you may want to sort the vector first.
Using algorithm:
std::size_t count_unique(const std::vector<int>& v)
{
std::size_t count = 0;
for (auto it = v.begin(); it != v.end(); )
{
auto it2 = std::find_if(it + 1, v.end(), [&](int e) { return e != *it; });
count += (it2 - it == 1);
it = it2;
}
return count;
}
Demo

How to find the minimal missing integer in a list in an STL way

I want to find the minimal missing positive integer in a given list. That is if given a list of positive integers, i.e. larger than 0 with duplicate, how to find from those missing the one that is the smallest.
There is always at least one missing element from the sequence.
For example given
std::vector<int> S={9,2,1,10};
The answer should be 3, because the missing integers are 3,4,5,6,7,8,11,... and the minimum is 3.
I have come up with this:
int min_missing( std::vector<int> & S)
{
int max = std::max_element(S.begin(), S.end());
int min = std::min_element(S.begin(), S.end());
int i = min;
for(; i!=max and std::find(S.begin(), S.end(), i) != S.end() ; ++i);
return i;
}
This is O(nmlogn) in time, but I cannot figure out if there is a more efficient C++ STL way to do this?
This is not an exercise but I am doing a set of problems for self-improvement , and I have found this to be a very interesting problem. I am interested to see how I can improve this.
You could use std::sort, and then use std::adjacent_findwith a custom predicate.
int f(std::vector<int> v)
{
std::sort(v.begin(), v.end());
auto i = std::adjacent_find( v.begin(), v.end(), [](int x, int y)
{
return y != x+1;
} );
if (i != v.end())
{
return *i + 1;
}
}
It is left open what happens when no such element exists, e.g. when the vector is empty.
Find the first missing positive, With O(n) time and constant space
Basiclly, when you read a value a, just swap with the S[a], like 2 should swap with A[2]
class Solution {
public:
/**
* #param A: a vector of integers
* #return: an integer
*/
int firstMissingPositive(vector<int> A) {
// write your code here
int n = A.size();
for(int i=0;i<n;)
{
if(A[i]==i+1)
i++;
else
{
if(A[i]>=1&&A[i]<=n&& A[A[i]-1]!=A[i])
swap(A[i],A[A[i]-1]);
else
i++;
}
}
for(int i=0;i<n;i++)
if(A[i]!=i+1)
return i+1;
return n+1;
}
};
Assuming the data are sorted first:
auto missing_data = std::mismatch(S.cbegin(), S.cend()-1, S.cbegin() + 1,
[](int x, int y) { return (x+1) == y;});
EDIT
As your input data are not sorted, the simplest solution is to sort them first:
std::vector<int> data(S.size());
std::partial_sort_copy (S.cbegin(), S.cend(), data.begin(), data.end());
auto missing_data = std::mismatch (data.cbegin(), data.cend()-1, data.cbegin()+1,
[](int x, int y) { return (x+1) == y;});
you can use algorithm the standard template library c ++ to work in your code.
#include <algorithm> // std::sort
this std::sort in algorithm:
std::vector<int> v={9,2,5,1,3};
std::sort(v.begin(),v.end());
std::cout << v[0];
I hope I understand what you, looking.
You can do this by building a set of integers and adding larger seen in the set, and holding the minimum not seen in as a counter. Once there is a number that is equal to the latter, go through the set removing elements until there is a missing integer.
Please see below for implementation.
template<typename I> typename I::value_type solver(I b, I e)
{
constexpr typename I::value_type maxseen=
std::numeric_limits<typename I::value_type>::max();
std::set<typename I::value_type> seen{maxseen};
typename I::value_type minnotseen(1);
for(I p=b; p!=e;++p)
{
if(*p == minnotseen)
{
while(++minnotseen == *seen.begin())
{
seen.erase(seen.begin());
}
} else if( *p > minnotseen)
{
seen.insert(*p);
}
}
return minnotseen;
}
In case you sequence is in a vector you should use this with:
solver(sequence.begin(),sequence.end());
The algorithm is O(N) in time and O(1) in space since it uses only a counter, constant size additional space, and a few iterators to keep track of the least value.
Complexity ( order of growth rate ) The algorithm keeps a subset only of the input which is expected to be of constant order of growth with respect the growth rate of the input, thus O(1) in space. The growth rate of the iterations is O(N+NlogK) where K is the growth rate of the larger subsequence of seen larger numbers. The latter is the aforementioned subsequence of constant growth rate i.e. K=1 , which results in the algorithm having O(N) complexity. (see comments)

std::max_element for second largest element?

The STL provides std::max_element to find the largest element in an iterable, e.g. like this:
std::vector<float>::const_iterator max =
std::max_element(obj.pt()->begin(), obj.pt()->end());
return std::distance(obj.pt()->begin(), max);
Is there also something to get an iterator for the n-th largest element?
(Note that max_element returns an iterator and this is actually important: Rather than for the value itself, I am looking for the position of the n-th largest element within the iterable.)
max_element() method can be used to get second largest element by passing lambda function which compares the element with the previously found largest element and if it is equal to the largest element then it'll simply skip that element.
auto largest = max_element(vec.begin(), vec.end());
auto secondLargest = max_element(vec.begin(), vec.end(),
[&largest](unsigned long &a, unsigned long &b) {
if (a == *largest) return true;
if (b == *largest) return false;
return a < b;
});
If you are specifically interested in the second-largest element, you can do a simple scan of the array in which most elements require a single comparison:
float second_largest_element(std::vector<float> vec) {
float m2, m1;
/* Check to make sure that vec has at least 2 elements!! */
std::tie(m2, m1) = std::minmax(vec[0], vec[1]);
for (auto it = vec.begin() + 2, limit = vec.end();
it != limit;
++it)
if (*it > m2) std::tie(m2, m1) = std::minmax(*it, m1);
return m2;
}
Getting the index of (or an iterator to) the second largest element is very similar, although std::minmax is less useful. Here's a very sloppy example:
template<typename T>
typename T::iterator second_largest(T& container) {
using iterator = typename T::iterator;
iterator limit = container.end();
iterator it = container.begin();
if (it != limit) {
iterator first = it++;
if (it != limit) {
iterator second = it++;
if (*first < *second) std::swap(first, second);
for (; it != limit; ++it) {
if (*second < *it) {
if (*first < *it) { second = first; first = it; }
else { second = it; }
}
}
return second;
}
return first;
}
return it;
}
You could also consider using std::accumulate to scan the array, although the explicit for loop is not complicated.
As Dyp mentioned in comment, if you are fine to alter the order of elements within your vector you can use std::nth_element as follows. On top if you use find again over vector you will get original position of the nth element from vector. Since nth_element modifies the positions, you have to keep a local copy of it before doing nth_element operation over vector.
2nd largest element:
std::vector<float> orig_vec=obj.pt;
std::nth_element(obj.pt().begin(), obj.pt().begin()+1,
obj.pt().end(), std::greater<float>());
float 2nd= *(obj.pt().begin()+1);
auto it=std::find(orig_vec.begin(), orig_vec.end(), 2nd);
nth largest element:
std::nth_element(obj.pt().begin(), obj.pt().begin()+n-1,
obj.pt().end(), std::greater<float>());
float nth= *(obj.pt().begin()+n-1);
auto it=std::find(orig_vec.begin(), orig_vec.end(), nth)
This is a trivial algorithm to implement in linear time. The naive approach would be to compare the first two values, and select them as the max and second largest values. Then you need to iterate over the other elements comparing each new element with both of them and adjusting your current max and second largest values. For most use cases that is probably more than enough. If you really care about performance (as in you care a lot) you will need to think what values you want to compare to minimize the number of comparisons.
Also note that float (floating point in general) have quirks... you might get funny values if your input contains NaN or infinite values.
It took me a while to find a solution, because I worked with const vector (so I can't use nth_element) and copy would be just wasting (especially, when vector is holding a bigger structures). So I came with this:
// Find 1st max
auto max1 = max_element(vec.begin(), vec.end());
if (max1 != vec.end())
// Use max1
// Find 2nd max. Split the vector into 2 parts, find max and merge results
auto max2Beg = max_element(vec.begin(), max1);
auto max2End = max_element(max1 + 1, vec.end());
auto max2 = max2Beg == max1 ? max2End :
max2End == vec.end() ? max2Beg : max(max2Beg, max2End);
if (max2 != max1 && max2 != vec.end())
// Use max2

Removing by index from a C++ vector using remove_if

We can use remove_if in C++ to remove elements from a vector in linear time based on a predicate that operates on the elements.
bool condition(double d) {...}
vector<double> data = ...
std::remove_if (data.begin(), data.end(), condition);
What if my condition depends not on the values, but on the indices? In other words, if I wanted to remove all the odd-indexed elements, or some arbitrary index set, etc?
bool condition(int index) {//returns whether this index should be removed}
vector<double> data = ...
std::remove_if (data.begin(), data.end(), ???);
You can use pointer arithmetic to find the index of a specific element that std::remove_if passes to the predicate:
std::remove_if(data.begin(), data.end(),
[&data](const double& d) { return (&d - &*data.begin()) % 2); });
Note that remove_if passes the result of dereferencing an iterator, and that's guaranteed to be a reference per Table 106 - Iterator requirements in the Standard.
I actually made an account only for this. Use awesomeyi answer. Is way cleaner.
int count = 0;
auto final = std::remove_if (data.begin(), data.end(), [&count](const double d) {
return (count++) % 2;
});
The standard does say that the predicate is applied exactly last - first times. And remove_if works with ForwardIterators.
This implies that the predicate is applied only once in the same order they originally appear in the sequence.
Unless of course, the library is trolling you, by keeping internal copies of the ForwardIterator.
Take advantage of the fact that lambas can capture variables. A quick example:
vector<double> data = {5, 3, 6, 7, 8};
int count = 0;
auto final = std::remove_if (data.begin(), data.end(), [&](const double d) {
bool b = false;
if(count % 2) b = true;
++count;
return b;
});
for(auto beg = data.begin(); beg != final; ++beg)
cout << *beg << endl;
Code will print: 5 6 8
An algorithm similar to std::remove_if, but passing indexes to it's predicate
template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_indexes_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
ForwardIt dest = first;
for(ForwardIt i = first; i != last; ++i)
if (!p(std::distance(first, i)))
*dest++ = std::move(*i);
return dest;
}

store positive number and negative in different vector

I am new to c++. I have a vector with size n. I want to search in the vector ad store positive and negative values in the new vectors. I don't know the number of positive and negative values.
Can anyone help me?
Here is yet another solution using std::partition_copy from the standard library:
std::vector<int> src, neg, pos;
std::partition_copy(
src.begin(), src.end(),
back_inserter(neg),
back_inserter(pos),
[](int value){ return value < 0; }
);
If you can rearrange items in your source vector, it's probably easiest to do something like this:
auto part = std::partition(input.begin(), input.end(), [](int p) { return p < 0; });
std::vector<int> neg(input.begin(), part);
std::vector<int> pos(part, input.end());
Assuming v being your std::vector<int> vector and 0 being positive, you just need to loop over the vector and store positive numbers in one vector and negative numbers in the other:
using std::vector;
vector<int> pos, neg;
for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++) {
if ((*it) >= 0) pos.push_back((*it));
else neg.push_back((*it));
}
A std::vector<int>::const_iterator is used here because you do not need to modify the original vector in any sense, you are just reading its values.
A variation of #Shos's answer, involving less pointers, which might be easier to read:
using std::vector;
vector<int> pos, neg;
for (auto& el : v)
{
if (el >= 0)
pos.push_back(el);
else
neg.push_back(el);
}