Can someone explain why lower_bound is working this way? - c++

lower_bound function of C++ returns a pointer to the first array element that is at least equal to x (the third argument passed to the function). Here is the code which I compiled online using an online compiler for C++.
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(1);
v.push_back(2);
cout<<lower_bound(v.begin(),v.end(),2)-v.begin()<<endl;
return 0;
}
Output I expected was 1 but actual result says 3. Can someone please explain why this is so?

https://en.cppreference.com/w/cpp/algorithm/lower_bound
The range [first, last) must be partitioned with respect to the expression element < value or comp(element, value), i.e., all elements for which the expression is true must precede all elements for which the expression is false. A fully-sorted range meets this criterion.
This order:
v.push_back(1);
v.push_back(2);
v.push_back(1);
v.push_back(2);
does not fulfill that criterion.

The range [first, last) must be partitioned with respect to the expression element < value or comp(element, value), i.e., all elements for which the expression is true must precede all elements for which the expression is false. A fully-sorted range meets this criterion.
https://en.cppreference.com/w/cpp/algorithm/lower_bound
Your input does not satisfy this requirement (not sorted), therefore the output is undefined.

std::lower_bound
// lower_bound/upper_bound example
#include <iostream> // std::cout
#include <algorithm> // std::lower_bound, std::upper_bound, std::sort
#include <vector> // std::vector
int main () {
int myints[] = {10,20,30,30,20,10,10,20};
std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector<int>::iterator low,up;
low=std::lower_bound (v.begin(), v.end(), 20); // ^
up= std::upper_bound (v.begin(), v.end(), 20); // ^
std::cout << "lower_bound at position " << (low- v.begin()) << '\n';
std::cout << "upper_bound at position " << (up - v.begin()) << '\n';
return 0;
}
std::sort (v.begin(), v.end()); is important, the number list has to be in ascend order.

Related

exclude non-duplicated int in vector

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

Seek item within vector

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.

why vector begin() pointing to second element of vector and while displaying a all element vector after few pusback() abort the program?

I am was just writing the small vector program in visual stdudio 2010.
#include <iostream>
#include <vector>
void main() {
using namespace std;
vector<int> myvector;
myvector.push_back(1);
myvector.push_back(2);
myvector.push_back(3);
myvector.push_back(4);
for( auto i = myvector.begin(); i != myvector.end(); ++i)
{
cout << myvector[*i] <<endl;
}
}
expected output should be
1 2 3 4 5
but I am getting this error:
I checked over web everywhere I have seen same sample program to use vector.
Note: in my program myvector is pointing to the second element of vector. I don't know why it is not pointing to the first element
.
Try This out you will get desired output It worked fine with g++4.2:
#include <iostream>
#include <vector>
using namespace std;
int main() {
using namespace std;
vector<int> myvector;
myvector.push_back(1);
myvector.push_back(2);
myvector.push_back(3);
myvector.push_back(4);
for( vector<int>::iterator i = myvector.begin(); i < myvector.end(); ++i)
{
cout<<*i<<endl;
}
//even check this second loop
for(int i=0;i<myvector.size();i++)
{
cout<<myvector.at(i)<<endl;
}
return 0;
}
You added four elements to the vector. So the valid range of indices for the subscript operator of class std::vector is 0 - 3
Let's consider the following statement
cout << myvector[*i] <<endl;
For the first iterator that is for the iterator that is equal to myvector.begin() the value of *i is equal to 1. For the last dereferenced iterator that is for the iterator that is equal to myvector.end() - 1 the value of *i is equal to 4.
As you are using these values as the indices of the subscript operator when the used range of indices is 1 - 4 This range does not coincide with the valid range of indices that is equal to 0 - 3. For example the vector has no element with the index equal to 4. And the compiler reports about this erroneous situation saying that vector subscript out of range
You could write simply as
cout << *i <<endl;
In this case you would get the predicted and correct result.:)
Or you could write
cout << myvector[*i - 1] <<endl;
In this case you would get the same correct result.
1 2 3 4
The indices of vectors as of arrays are always start with 0.
Take into account that if your compiler supports features of the C++ 2011 Standard then instead of these statements
vector<int> myvector;
myvector.push_back(1);
myvector.push_back(2);
myvector.push_back(3);
myvector.push_back(4);
you could write simply
vector<int> myvector = { 1, 2, 3, 4 };
that uses the initialization-list constructor.

Using std::max_element on a vector<double>

I'm trying to use std::min_element and std::max_element to return the minimum and maximum elements in a vector of doubles. My compiler doesn't like how I'm currently trying to use them, and I don't understand the error message. I could of course write my own procedure to find the minimum and maximum, but I'd like to understand how to use the functions.
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
double cLower, cUpper;
vector<double> C;
// Code to insert values in C is not shown here
cLower = min_element(C.begin(), C.end());
cUpper = max_element(C.begin(), C.end());
return 0;
}
Here is the compiler error:
../MIXD.cpp:84: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment
../MIXD.cpp:85: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment
What am I doing wrong?
min_element and max_element return iterators, not values. So you need *min_element... and *max_element....
As others have said, std::max_element() and std::min_element() return iterators, which need to be dereferenced to obtain the value.
The advantage of returning an iterator (rather than just the value) is that it allows you to determine the position of the (first) element in the container with the maximum (or minimum) value.
For example (using C++11 for brevity):
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0};
auto biggest = std::max_element(std::begin(v), std::end(v));
std::cout << "Max element is " << *biggest
<< " at position " << std::distance(std::begin(v), biggest) << std::endl;
auto smallest = std::min_element(std::begin(v), std::end(v));
std::cout << "min element is " << *smallest
<< " at position " << std::distance(std::begin(v), smallest) << std::endl;
}
This yields:
Max element is 5 at position 4
min element is 1 at position 0
Note:
Using std::minmax_element() as suggested in the comments above may be faster for large data sets, but may give slightly different results. The values for my example above would be the same, but the position of the "max" element would be 9 since...
If several elements are equivalent to the largest element, the iterator to the last such element is returned.
min/max_element return the iterator to the min/max element, not the value of the min/max element. You have to dereference the iterator in order to get the value out and assign it to a double. That is:
cLower = *min_element(C.begin(), C.end());

C++ Erase vector element by value rather than by position? [duplicate]

This question already has answers here:
How do I remove an item from a stl vector with a certain value?
(12 answers)
Closed 6 years ago.
vector<int> myVector;
and lets say the values in the vector are this (in this order):
5 9 2 8 0 7
If I wanted to erase the element that contains the value of "8", I think I would do this:
myVector.erase(myVector.begin()+4);
Because that would erase the 4th element. But is there any way to erase an element based off of the value "8"? Like:
myVector.eraseElementWhoseValueIs(8);
Or do I simply just need to iterate through all the vector elements and test their values?
How about std::remove() instead:
#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());
This combination is also known as the erase-remove idiom.
You can use std::find to get an iterator to a value:
#include <algorithm>
std::vector<int>::iterator position = std::find(myVector.begin(), myVector.end(), 8);
if (position != myVector.end()) // == myVector.end() means the element was not found
myVector.erase(position);
You can not do that directly. You need to use std::remove algorithm to move the element to be erased to the end of the vector and then use erase function. Something like: myVector.erase(std::remove(myVector.begin(), myVector.end(), 8), myVec.end());. See this erasing elements from vector for more details.
Eric Niebler is working on a range-proposal and some of the examples show how to remove certain elements. Removing 8. Does create a new vector.
#include <iostream>
#include <range/v3/all.hpp>
int main(int argc, char const *argv[])
{
std::vector<int> vi{2,4,6,8,10};
for (auto& i : vi) {
std::cout << i << std::endl;
}
std::cout << "-----" << std::endl;
std::vector<int> vim = vi | ranges::view::remove_if([](int i){return i == 8;});
for (auto& i : vim) {
std::cout << i << std::endl;
}
return 0;
}
outputs
2
4
6
8
10
-----
2
4
6
10