Suppose we have a set of N ranges, (A1, B1) (A2, B2) (A3, B3) ... (An, Bn), where Ai denotes the starting point and Bi denotes the ending point of a range. (Ai, Bi are positive integers)
How do we check using Binary Search if the given integer, say X, exists in at least one of the N ranges?
My approach:
Sort the ranges by x-coordinate first and then by y-coordinate.
Find the smallest x-coordinate greater or equal to X.
Check if that range is satisfied.
If yes, we have a solution.
Now, if that range doesnt contain X, what should be my next step?
Or, should the solution be entirely different?
What I got from your problem description is that you have pairs
like (a1,b1) , (a2,b2)
. Where ax
is start of range and bx
is end. Now you are given a number n
and you want to search if that number is in any of ranges.
First sort then merge the overlapping ranges and then apply binary search:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector < pair <int , int> > b;
b.push_back(make_pair(5,10));
b.push_back(make_pair(75,100));
b.push_back(make_pair(33,67));
b.push_back(make_pair(9,21));
b.push_back(make_pair(28,67));
int m = b.size();
sort(b.begin(), b.end());
int j = 0;
for (int i = 1; i < m; i++) {
if (b[i].first <= b[j].second) {
if (b[i].second > b[j].second) {
b[j].second = b[i].second;
}
}
else {
j++;
b[j] = b[i];
}
}
m = j + 1;
for(int i = 0; i< m;i ++) {
cout << b[i].first << " " << b[i].second << endl;
}
// Apply binary search now
return 0;
}
I hope this will solve your problem. I have left the binary search part for you as exercise.
First of all, if the ranges aren't sorted, you're better off checking one by one instead of doing any fancy binary search, because checking each range will be at most O(n), whereas sorting and then binary searching will be at least O(n log n).
Anyway, in this case I'd consider all the ranges with the same x-coordinate to be a single node, so when you're binary-searching, the middle node you get will actually be the group of ranges that have the same x-coordinate. You'd then check the y-coordinate of the last range in that node. If the number is not between those two, then the number is not contained in any of the ranges of that node, so you should either go left or right depending on whether the number is higher or lower than the x or y-coordinates.
Here's a full working example in Python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import itertools
MAX = 50
NUM_RANGES = 30
THE_NUMBER = random.randint(0, MAX)
ranges = []
# Generate random ranges
for e in range(NUM_RANGES):
x = random.randint(0, MAX - 1)
y = random.randint(x + 1, MAX)
ranges.append((x,y))
# Group the ranges by starting coordinate
grouped_ranges = {x: [e for e in ranges if e[0] == x] for x in (e[0] for e in ranges)}
## Binary search
gkeys = grouped_ranges.keys()
gkeys_range = [0, len(gkeys)]
get_mid_key = lambda: (gkeys_range[1] + gkeys_range[0])/2
get_mid = lambda: grouped_ranges[gkeys[get_mid_key()]]
print "THE NUMBER:", THE_NUMBER
print "THE RANGES:", grouped_ranges
while 1:
# Get middle element
mid = get_mid()
print gkeys_range
old_range = gkeys_range[:]
if THE_NUMBER < mid[0][0]:
gkeys_range[1] = get_mid_key()
elif THE_NUMBER > mid[-1][1]:
gkeys_range[0] = get_mid_key()
else:
print "In this range:", mid
break
if gkeys_range == old_range:
print "Not in any range"
break
来源:https://stackoverflow.com/questions/26296761/check-if-a-number-exists-in-a-given-set-of-ranges