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);
}
Related
I have to find 4 the biggest numbers in a const vector and return their positions. I want this code to have the best time and space complexity. My first idea is to copy this const vector into vector and bubble sort it 4 times. That gives me 4*N but i have to create a vector. Second idea is to put everything from this const vector into priority_queue. That gives me a N*log2(N) time complexity without creating another variables. The maximum of N is around 100.
Is there any other options to do it in the fastest and the least space-consuming way?
EDIT: It doesn't matter which one is the biggest, I just need to return position of this 4 items in the input vector.
O(n) solution
std::vector<int>::iterator max1 = v.begin(), max2 = v.begin(), max3 = v.begin(), max4 = v.begin();
for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
if((*max1) < (*it)) {
max4 = max3;
max3 = max2;
max2 = max1;
max1 = it;
} else if((*max2) < (*it)) {
max4 = max3;
max3 = max2;
max2 = it;
} else if((*max3) < (*it)) {
max4 = max3;
max3 = it;
} else if((*max4) < (*it)) {
max4 = it;
}
}
You can implement this quite easily with an extra vector, and the nth_element algorithm, which is O(n) time:
std::vector<int> const v = ...;
// create a vector of elements with original indexes
std::vector<std::pair<int,int>> res;
// populate the result vector
int k = 0;
for (int i : v)
res.push_back({i,k++});
// find the maximum 4 elements
std::nth_element(res.begin(), res.begin() + 4, res.end(),
[](auto const &a, auto const &b) { return a.first > b.first; });
Here's a demo.
Note that this solution uses O(n) extra space. If N grows large, then this might not be the right approach for finding just 4 largest elements. It's still a good approach if you want the M largest elements, where M grows like N.
Yes, use a heap of size four. Then you iterate through the vector and update the heap accordingly.
Sample code using std heap methods and finding minimum values (from here) follows.
const std::vector<int> input;
const size_t n = 4;
std::vector<int> ret(n);
auto dfirst = ret.begin(), dlast = ret.end();
// initialize heap with infinity distances
std::fill(dfirst, dlast, 100000000000); // do better here
for (auto it = input.begin(); it != input.end(); ++it)
{
if (*it < *dfirst) {
// remove max. value in heap
std::pop_heap(dfirst, dlast); // add comparator as third arg
// max element is now on position "back" and should be popped
// instead we overwrite it directly with the new element
*(dlast-1) = *it;
std::push_heap(dfirst, dlast); // add comparator as third arg
}
}
std::sort_heap(dfirst, dlast); // remove if not needed, or add comparator as third arg
return ret;
Adapt accordingly:
Use a pair of index, value in the heap to keep track of positions which you like to return
Use comparator that compares on value in the pair and establishes a desc. ordering
This is more generic than #Jugal Rawlani's solution if your number n might change/grow in the future. Otherwise his idea wins.
read the 4 first elements into a vector of 4. sort this vector so that minimum of the 4 is in index 0.
loop on remaining items of the const vector, if current value > min, replace it and re-sort the 4 element 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
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)
I have a vector of integers. which contains numbers. I want to count the number of occurrences of every number in this vector. So what will be the optimum way to do this. As I am new to Vectors please let me know any optimum method.
You can use a hash table, implemented by std::unordered_map. For example:
#include <unordered_map>
#include <vector>
void count_occurrence(std::unordered_map<int,int>& m, std::vector<int>& v){
for (auto itr = v.begin(); itr != v.end(); ++itr){
++m[*itr];
}
}
//...somewhere else
//you already have std::vector v filled
std::unordered_map<int,int> m;
count_occurrence(m, v);
//print the number of occurrences of 1
std::cout<<m[1]<<std::endl;
You could sort the elements of the vector
Iterate through vector
Store the current integer as x
Compare current index to previous index.
If they are equal, increment another variable as f
If they are unequal, begin the cycle again
This of course is by no means a step by step instruction, but it contains enough direction to get you going
To find the mode of a number of integers stored in an array/list/vector/etc. where v is the DS and num is the number of integers.
You may use the following technique:
Its simple and sober.
i = 0;
int m = 0, mode, c = 0, nc = 0;
while(i<num)
{
c = 0;
nc = v[i];
c++;
i++;
while(nc == v[i])
{
c++;
i++;
}
if(m < c)
{
m = c;
mode = nc;
}
}
My question is very similar to How to find an item in a std::vector? However, I want to go further, suppose the item I am searching for appears several times in the vector, and I want to obtain its positions in the vector as well. For example, the vector I have is [ 1 3 4 3 7], and the item I want to search is 3. Then the positions of the item is 1 and 3. Using the std::find function, I can only obtain its first position in the vector. Any ideas?
Just stick it in a while loop,
auto i = std::find(v.begin(), v.end(), n);
std::vector<std::size_t> result;
while(i != v.end())
{
result.push_back(std::distance(v.begin(), i));
i = std::find(i + 1, v.end(), n);
}
Use std::find successive times, and then put all the results together. Use as first of the range in which you find, the position that the previous std::find returned to you plus one.
You can use std::find multiple times:
std::vector<int> vec;
// fill the vector with numbers
std::vector<int>::iterator it = vec.begin();
while (it != vec.end())
{
it = std::find(it, vec.end(), 3);
// do something with *it
if (it != vec.end())
it++;
}
Or you can simply use std::for_each:
std::vector<int> vec;
// fill the vector with numbers
std::for_each(vec.begin(), vec.end(), [&](int i)
{
if (i == 3)
{
// do something
}
});
If you are looking for the indexes/iterators for the items, you can simply use a custom loop:
std::vector<int> vec;
// fill the vector with numbers
std::vector<int> results;
for (std::size_t i = 0; i < vec.size(); ++i)
{
if (vec[i] == 3)
{
results.push_back(i);
}
}
results will then hold all of the indexes for elements matching your criteria (in this case, ==3).