针对范围对的高效查找算法设计(不准用数组)

题目链接在:针对一群范围对的最快查找算法设计(不要用数组),是我目前遇到的一个较棘手的问题。

描述如下:

假如有一群范围对,格式为:<范围表示,该范围对应的结果值>,设计一个最快查找算法,使得给定一个值,输出该值所在范围对的结果值。
注意:范围对之间没有交集,即不可能存在<1, 10>和<2, 11>这样的两个范围对。

例如有以下几个范围对:
<<1, 2>, 20>
<<3, 37>, 27>
<<48, 57>, 28>
<<58, 63>, 27>
<<97, 128>, 122>
<<129, 149>, 12>
<<150, 189>, 13>
<<200, 245>, 14>
<<246, 256>, 129>
<<479, 560>, 12>

假如给定一个数100,则根据题意应输出122,因为100属于范围对<97, 128>

要求:不要用范围对作为下标用数组来存储,因为范围对可能非常大。

对于这个问题,思考许久,有了下面几个思路


1. 用STL map来存储这些范围对(key)及对应的结果集(value),用map进行查找

范围对定义如下:

复制代码
class range {
public:
    int from;                                                                  
    int to; 

public:
    range(): from(-1), to(-1) {}
    range(int f, int t): from(f), to(t) {}
};
复制代码

map定义为:

typedef map<range*, int> range_map;

但这里有个问题,map的key是自定义类型,一般需要自定义比较函数才能进行查找,一般的自定义比较函数如下:

struct cmp_func {
    bool operator()(const range* lc,const range* rc) const {
        return (lc->from < rc->from) || (lc->from == rc->from && lc->to < rc->to);
    }
};

但这样的比较函数并不适用于我们的需求,因为我们要求查询的并不是一个范围对,即并不是查询map中有没有<3, 37>这样的范围对,而是要求给定一个值,查询这个值属于哪个范围对,那么能不能自定义一个这样的比较函数呢?以上面那个例子为例,如果我们查找35这个数,我们将35包装成一个范围对<35, 35>,然后查找它包含在map中的哪个范围对,上面的例子是包含在<3, 37>这样的范围对,这样就找到了,也就是两个key相等,只要它们包含在同一个范围对即可。这似乎有点奇怪,违背了通常意义上的比较含义(也就是两个key相等,两个key的组成部分都应该相同才是)。不管如何,这样的比较函数还是比较简单的,如下:

struct cmp_func {
    bool operator()(const range* lc,const range* rc) const {
        return lc->to < rc->from;
    }
};

这样就实现了我们用map的find函数来查找给定的一个数属于哪个范围对了。当然,这时我们的map定义就变成了:

typedef map<range*, int, cmp_func> range_map;

用map查找表面上看上去应该挺高效的,至少比一个个顺序查找要快吧,但事实却并非如此。我用未自定义比较函数的map顺序查找和自定义上面比较函数的map find查找,结果却发现用自定义比较函数后的效果并不好,竟然比顺序查找还要慢,下面的粗糙的测试程序:

复制代码
#include<iostream>
#include<stdio.h>
#include<map>
#include<sys/time.h>
using namespace std;

class range {
public:
    int from;                                                                  
    
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值