I'm new to C++, I came from Swift background, and I'm thankful for your help in advance.
I have a vector that contains int values. Some of them are repeated.
My task here is to get the largest repeated value from the vector.
Example:
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(8);
myVector.push_back(4);
myVector.push_back(4);
I need a function that returns 4 because it's the largest duplicate int in the vector.
Thanks again, and please, if you have any question, please ask it instead of downvoting.
Solution based only on std algorithms:
Sort the list using std::sort.
Iterate backwards over its elements and detect the first one that is equal to its predecessor using std::adjacent_find and reverse iterators.
I doubt it gets simpler than this. For your enjoyment:
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1,2,3,3,4,4,4,5,6,7,7,8};
std::sort(v.begin(), v.end());
auto result = std::adjacent_find(v.rbegin(), v.rend());
if(result == v.rend())
std::cout << "No duplicate elements found.";
else
std::cout << "Largest non-unique element: " << *result;
}
Live example on Coliru.
Properties:
Zero space overhead if the list can be sorted in place.
Complexity: O(N log(N)) less than comparisons and K equality comparisons where K is equal to the number of unique elements larger than the one you're after.
Lines of code making up the algorithm: 2
You could use a map, as someone who commented above, and then place the number of appearances of each element of the vector. Afterwards, you take the maximum element via a custom comparator.
Ideone
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
int largestRepeatingNumber(const std::vector<int> & vec)
{
std::map<int, int> counter;
std::for_each(std::begin(vec), std::end(vec), [&counter] (int elem) {
counter.find(elem) == counter.end() ? counter[elem] = 1 : ++counter[elem]; });
return std::max_element(std::begin(counter), std::end(counter), [] (auto lhs, auto rhs) {
if (lhs.second == rhs.second)
return lhs.first < rhs.first;
return lhs.second < rhs.second;
})->first;
}
int main()
{
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(8);
myVector.push_back(4);
myVector.push_back(4);
myVector.push_back(3);
myVector.push_back(3);
std::cout << largestRepeatingNumber(myVector);
return 0;
}
I have used the lower bound and upper bound
so strategy is
1)Sort the original vector (so that can use unique function on it)
2)find unique (copy the unique values to a vector so that we can use it to find the values in original vector , not extra search)
3)Find the lower and upper bound value with max distance
for example 1 4 4 8
4 will have max distance
5)Store in map using the count as index (map is ordered so max duplicate value will be at the end )
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int main()
{
std::vector<int> myVector,myvec,counter;
map<int,int> maxdupe;
myVector.push_back(1);
myVector.push_back(8);
myVector.push_back(4);
myVector.push_back(4);
sort(myVector.begin(),myVector.end());
std::unique_copy(myVector.begin(), myVector.end(), std::back_inserter(myvec));
std::copy(myvec.begin(), myvec.end(), std::ostream_iterator<int>(std::cout, " "));
cout<<endl;
for(auto i = myvec.begin(); i!=myvec.end();i++)
{
auto lower = std::lower_bound(myVector.begin(), myVector.end(), *i);
auto upper = std::upper_bound(myVector.begin(), myVector.end(), *i);
maxdupe[upper - lower] = *i;
}
for(auto i= maxdupe.begin();i!= maxdupe.end();i++)
{
cout<<i->first<<i->second<<endl;
}
return 0;
}
Output
1 4 8
18
24
Program ended with exit code: 0
Related
Currently I'm only aware of the following:
vector<int> nums= {3,2,1,0,2,3,3,1,0,0};
return max_element(nums.begin(), nums.end())-nums.begin();
But in that case it would return the lowest index of the maximum element.
A way around it would be:
vector<int> nums= {3,2,1,0,2,3,3,1,0,0};
int n = *max_element(nums.begin(), nums.end());
for(int i=nums.size()-1; i>-1; i--){
if(nums[i]==n) {
return i;
break;
}
}
But is there any simpler way that I can achieve the same result without bruteforcing it?
You could iterate backwards by using reverse iterators, and get the distance:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> nums= {3,2,1,0,2,3,3,1,0,0};
auto iter = std::max_element(nums.rbegin(), nums.rend()).base();
std::cout << std::distance(nums.begin(), std::prev(iter));
}
Output:
6
See what base() does when it comes to reverse iterators.
Whereas std::max_element returns the first largest element, std::minmax_element returns the last one (for the largest).
So you might do:
std::vector<int> nums = {3,2,1,0,2,3,3,1,0,0};
return std::distance(nums.begin(),
std::minmax_element(nums.begin(), nums.end()).second);
Trying to solve 'move zeros' question. I have to shift all zeros of vector at last and then all other numbers need to be arranged in ascending order.
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int position = nums.size()-1;
for(int i=0;i<nums.size();i++){
if(nums[i]==0 && nums[position]!=0 && position>=i){
int temp=nums[i];
nums[i]=nums[position];
nums[position]=temp;
position-=1;
}
for(int i=0;i<nums.size();i++){
cout<<nums[i]<<" ";
}
cout<<endl;
}
std::partial_sort(nums.begin(), nums.begin()+position, nums.end());
}
};
Take a look at what std::partial_sort() does:
Rearranges elements such that the range [first, middle) contains the sorted middle - first smallest elements in the range [first, last).
In other words, the partitioning you did is ignored.
There are a few alternatives:
std::sort() it all, and std::rotate() the zeroes to the end.
Sort it all with a custom comparator considering zero the biggest value.
std::partition() the range so zeroes are at the end, and then sort the front.
Here is a solution using std::partition and then std::sort.
#include <algorithm>
#include <vector>
#include <iostream>
void moveZeroes(std::vector<int>& nums)
{
// Partition by placing zeros on the right. Returns the partition point
auto iter = std::partition(nums.begin(), nums.end(), [&](int n)
{ return n != 0; });
// Now sort the items at the left of the partition.
std::sort(nums.begin(), iter);
}
int main()
{
std::vector<int> nums = {0,1,0,3,12};
moveZeroes(nums);
for (auto i : nums)
std::cout << i << " ";
}
Output:
1 3 12 0 0
The first step is to partition the elements. The return value for std::partition will be an iterator pointing to the partition point.
The last step is to now sort all of the items at the left of the partition, since the zeros were placed on the right of the partition.
void moveZeroes(vector<int>& nums) {
std::sort(begin(nums),end(nums),[](int x,int y){if(!x)return false;if(!y)return true; return x<y;});
}
seems simpler.
I have two containers std::set and std::vector and my task is to return elements from std::vector which are present in std::set. What is the most effective way to achieve it?
Simple solution:
Iterate through elements of vector and call set.find on each and then vector.erase if not found.
How about just looking for every element? If your vector is not sorted, then there's no way around n log(n)
#include <algorithm>
std::vector<int> result;
for(auto&& el: myvector) {
auto it_found = myset.find(el);
if(it != myset.end())
result.push_back(*it_found);
}
Now result has all the elements that are in both.
PS: Haven't compiled the code, there might be slight errors.
You can use more STL :)
#include <algorithm>
#include <set>
#include <vector>
#include <iostream>
#include <iterator>
int main() {
std::vector<int> v {5, 4, 3, 2, 1};
std::set<int> s {1, 3, 5};
v.erase(std::remove_if(v.begin(), v.end(),
[&s](int a) { return s.find(a) == s.end(); }),
v.end());
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
}
Shortest way is probably to use std::set_intersection. But you should sort a vector to make it work:
int main()
{
std::set<int> s{1,2,3,4,5,6,7,8};
std::vector<int> v{7,5,10,9};
std::sort(v.begin(), v.end()); // should not bother you if vector is small
std::vector<int> intersection;
std::set_intersection(s.begin(), s.end(), v.begin(), v.end(), std::back_inserter(intersection));
for(int n : intersection)
std::cout << n << ' ';
}
Prints: 5 7
Depending on relative size of set and vector, remove_if may be the right thing...
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::set<int> s{1,2,3,4,5,6,7,8};
std::vector<int> v{7,5,10,9};
v.erase(std::remove_if(v.begin(), v.end(), [&](int e){return s.count(e) == 0;}), v.end());
for(int n : v)
std::cout << n << ' ';
}
If you look for the most cpu-effective way of doing this in terms of complexity, have additional memory and a good hash function, you can do it in O(n + m):
std::vector<int> v;
std::set<int> s;
std::unordered_set<int> us{s.cbegin(), s.cend(), s.size()};
v.erase(
std::remove_if(v.begin(), v.end(),
[&us] (const int entry) { return us.find(entry) == us.cend(); }),
v.end());
Explanation: you iterate over your set once (O(m)) to prepare unordered_set. Then you iterate through your vector once (O(n)), performing unordered_set::find (0(1)) each step. It gives you the resulting complexity of O(n+m).
Also, the size of unordered_set being equal to the size of set and a good hash function helps to reduce constant part in complexity of std::unordered_set::find.
See live example.
Bear in mind, however, that lower complexity doesn't necessarily mean faster execution in particular circumstances (for example, because of extra allocations).
I have a vector of real values, sorted by increasing order.
These values can be within the range [0, 1]. Then I pick a value x within this range and I need to find which is the index of the smaller value greater or equal to x.
I can solve this problem by iterating over the whole array:
vector<double> values;
double x;
for (auto val : values)
{
if (x <= values)
{
// found
break;
}
}
Is there a faster way to get the same result? I was thinking about a binary search, but how to implement it?
Use std::lower_bound:
#include <iterator>
#include <algorithm>
std::distance(begin(values)
, std::lower_bound(begin(values), end(values), x));
If the item doesn't exist, it'll give you an index one greater than that of the last element.
DEMO
The function lower_bound might meet your demand,and you can use it like below:
iter =lower_bound(values.begin(),values.end(),x);
You can use operator[] to directly access the items in a vector just like an array, instead of using an iterator to start from the begin. I assume you already know Binary Search. Implement it in an array is something you can find anywhere, so I won't explain it to you here. Just treat the vector as an array.
You know SO is not a site that you request someone to write you the code, so take this example of std::binary_search and make your way:
// binary_search example
#include <iostream> // std::cout
#include <algorithm> // std::binary_search, std::sort
#include <vector> // std::vector
bool myfunction (int i,int j) { return (i<j); }
int main () {
int myints[] = {1,2,3,4,5,4,3,2,1};
std::vector<int> v(myints,myints+9); // 1 2 3 4 5 4 3 2 1
// using default comparison:
std::sort (v.begin(), v.end());
std::cout << "looking for a 3... ";
if (std::binary_search (v.begin(), v.end(), 3))
std::cout << "found!\n"; else std::cout << "not found.\n";
// using myfunction as comp:
std::sort (v.begin(), v.end(), myfunction);
std::cout << "looking for a 6... ";
if (std::binary_search (v.begin(), v.end(), 6, myfunction))
std::cout << "found!\n"; else std::cout << "not found.\n";
return 0;
}
As Piotr said, this will not give you the index, but a yes/no answer. However, is should be the simplest approach, thus the fastest.
I'm sitting on a small exercise in C++ Primer (3.23) for almost 2 days. I've tried many ways of assigning a value to vector<int>. I'll give you an actual exercise on which I work and code with which I came so far, but its totally wrong. I did a lot of research but found nothing useful.
Write a program to create a vector with 10 int elements. Using an iterator, assign each element a value that is twice its current value. Test the program by printing vector
And this is my code
int main(){
vector<int> num(10);
for (auto it=num.begin();it != num.end() ;++it)//iterating through each element in vector
{
*it=2;//assign value to vector using iterator
for (auto n=num.begin() ;n!=num.end();++n)//Iterating through existing elements in vector
{
*it+=*n;// Compound of elements from the first loop and 2 loop iteration
}
cout<<*it<<" ";
}
keep_window_open("~");
return 0;
}
My problem is I don't know how to assign an int value to each vector element using an iterator (I did to 1 but not to the five elements)! In addition I was breaking my head on how to do this exercise with 10 elements in vector, to each element must be a different value and an iterator must do the assignment.
Thank you for your time.
Here's a much cleaner version of the accepted answer, using the concept of incrementing the iterator instead of a for loop:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> num(10);
int n = 1;
vector<int>::iterator it = num.begin();
vector<int>::iterator itEnd = num.end();
while (it != itEnd)
{
*it = n = n*2;
cout << *it << " ";
it++;
}
}
You can do like this:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> num(10);
int initial_value = 2;
*num.begin() = initial_value;
cout<<*num.begin()<<" ";
for (std::vector<int>::iterator it=num.begin()+1; it != num.end() ;++it)//iterating thru each elementn in vector
{
*it=*(it-1) * 2;//assign value wtih 2 times of previous iterator
cout<<*it<<" ";
}
return 0;
}
You just need to give some initial value to the first iterator and the rest is calculated in a for loop