检查给定范围集中是否存在数字

时间:2014-10-10 09:59:36

标签: algorithm sorting binary-search

假设我们有一组N个范围,(A1,B1)(A2,B2)(A3,B3)...(An,Bn),其中Ai表示起点,Bi表示a的终点。范围。 (Ai,Bi是正整数)

如果给定的整数(例如X)存在于N个范围中的至少一个范围内,我们如何使用二进制搜索进行检查?

我的方法:

  1. 首先按x坐标排序,然后按y坐标排序。

  2. 找到大于或等于X的最小x坐标。

  3. 检查是否满足该范围。

  4. 如果是,我们有解决方案。

  5. 现在,如果该范围不包含X,我的下一步应该是什么?

    或者,解决方案应该完全不同吗?

2 个答案:

答案 0 :(得分:1)

首先,如果范围没有排序,你最好逐个检查而不是进行任何花哨的二进制搜索,因为检查每个范围最多是O(n),而排序然后是二进制搜索将至少为O(n log n)。

无论如何,在这种情况下,我会将具有相同x坐标的所有范围视为单个节点,因此当您进行二进制搜索时,您获得的中间节点实际上将是具有的范围组相同的x坐标。然后,您将检查该节点中最后一个范围的y坐标。如果数字不在这两个之间,则该数字不包含在节点的任何范围内,因此您应该向左或向右,具体取决于数字是高于还是低于x或y坐标。

这是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

答案 1 :(得分:1)

我从您的问题描述中得到的是pairs (a1,b1) , (a2,b2)ax是范围的开头且bx结束的位置。现在,您将获得一个数字n,并且您想要搜索该数字是否在任何范围内 首先排序,然后合并重叠范围,然后应用二进制搜索:

#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;
}

我希望这能解决你的问题。我已经把二元搜索部分留给你了。