Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the key equal (if key exists in the map) or strictly less than given input in a map

Tags:

c++

stl

stdmap

I am taking numberOfItems number of keys as input and putting them in a map like this:

int numberOfItems;
int query;
scanf("%d",&numberOfItems);
int temp;
map<int,int> iimap;
for(int i=0;i<numberOfItems;i++)
{
    scanf("%d",&temp);
    iimap.insert(make_pair(temp,1));
}
printf("Enter query: ");
scanf("%d",&query);
int VstrictlyLessOrEqual = FstrictlyLessOrEqual(query);

I set the default key for each input = 1; So, the non-existent key has value =0 .

6 100 5 4 3 2 1 50

For this input (the first input 6 is numberOfItems & the last input 50 is query) FstrictlyLessOrEqual() should return value 5

like image 567
Utshaw Avatar asked Jan 05 '23 19:01

Utshaw


2 Answers

You want to use std::map's upper_bound() or lower_bound() method :

upper_bound()

upper_bound() returns an iterator to the first key that's higher than the key searched for. So:

  1. Call upper_bound().

  2. If upper_bound() returned begin() this means that the searched for is lower than the lowest key in the map.

  3. Otherwise decrement the iterator. It will now point to a key either equal to the key searched for, or the next smaller key.

lower_bound()

lower_bound() returns an iterator to the first key in the map that's equal or greater than the key searched for, so to accomplish your goals you will need to:

  1. Call lower_bound()

  2. Check if lower_bound() did not return end(), and the iterator's key is the same key you searched for. The key exists in the map.

  3. Otherwise, check if lower_bound() returned the map's begin() iterator value. If so, this means that the key you searched for is lower than the first key in the map, and so such value exists.

  4. Otherwise, decrement the returned iterator. The key you searched for does not exist in the map, and the decremented iterator points to a key that's the next smallest in the map.

like image 178
Sam Varshavchik Avatar answered Jan 11 '23 22:01

Sam Varshavchik


If the the default ordering (std::less) of keys is not a requirement, then using std::greater as key_compare with a single lower_bound() call would do the trick.

// std::greater instead of default std::less
std::map<int, int, std::greater<int>> m = {{3, 0}, {5, 0}, {7, 0}, {9, 0}};

auto it = m.lower_bound(1);
printf("%d\n", it != m.end() ? it->first : -1); // prints -1
it = m.lower_bound(3);
printf("%d\n", it != m.end() ? it->first : -1); // prints 3
it = m.lower_bound(4);
printf("%d\n", it != m.end() ? it->first : -1); // also prints 3
like image 38
Mingliang Avatar answered Jan 11 '23 22:01

Mingliang