从一组 IP range --> value 的数据中查找单个 IP,允许使用 C++ STL。
我的解法:
每个 range 的表示是三元组:(start ip, end ip, value)
struct IPrange // 闭区间 [startIp, endIp]
{
uint32_t startIp;
uint32_t endIp; // startIp <= endIp
int value; // 或者是 Value* pValue;
};
写一个函数,输入是一个 ip,类型为 uint32_t,如果某个 range 包含它,那么输出该 IP range 的 value,否则返回
-1。
假设合法的 value 不含 -1。如果 value 不是 int 而是 Value*,那么返回 NULL 表示失败。
假设 IP range 不重复,那么一个 ip 至多对应一个 value。
数据结构:vector<IPRange> ranges;
定义排序关系:
bool operator<(const IPrange& lhs, const IPrange& rhs)
{
return lhs.startIp < rhs.startIp;
}
整个 vector 是排好序且没有重复元素:
sort(ranges.begin(), ranges.end());
assert(adjacent_find(ranges.begin(), ranges.end()) == ranges.end());
其中 operator==() 定义为:
bool operator==(const IPrange& lhs, const IPrange& rhs)
{
return lhs.startIp == rhs.startIp;
}
然后,find_ip_value 函数可以用 lower_bound 实现:
int findIpValue(const vector<IPrange>& ranges, uint32_t ip)
{
int result = -1;
if (!ranges.empty())
{
IPrange needle = { ip, 0, 0 };
vector<IPrange>::const_iterator it = lower_bound(ranges.begin(),
ranges.end(), needle);
if (it == ranges.end())
{
--it;
}
else if (it != ranges.begin() && it->startIp > ip)
{
--it;
}
if (it->startIp <= ip && it->endIp >= ip)
{
result = it->value;
}
}
return result;
}
算法的复杂度为 O(log N), N = ranges.size()。
考虑 range 是 [255.255.0.0, 255.255.255.255] => 香港。(这是个闭区间)
输入 255.255.255.255,那么输出应该是"香港",但是他的代码判断 iter != ipmap.end(),认为 value 不存
在。
On Apr 3, 12:05 pm, lzprgmr <baiyanhu...@gmail.com> wrote:
> 看来出题者自己也给出了算法,也是利用了lower_bound/upper_bound:http://blog.csdn.net/whinah/archive/2010/08/05/5791255.aspx
>
> Blog:http://www.cnblogs.com/baiyanhuang/
> Douban:http://www.douban.com/people/baiyanhuang/
>
> 2011/4/3 Shuo Chen <giantc...@gmail.com>
On Apr 3, 12:16 pm, lzprgmr <baiyanhu...@gmail.com> wrote:
> 请教个问题,你一般会在代码中用类似于adjacent_find这样O(n)的方法来assert一个序列是否有重复,或者是否有序吗?
>
> Blog:http://www.cnblogs.com/baiyanhuang/
> Douban:http://www.douban.com/people/baiyanhuang/
>
> 2011/4/3 lzprgmr <baiyanhu...@gmail.com>
>
>
>
>
>
>
>
> > 看来出题者自己也给出了算法,也是利用了lower_bound/upper_bound:
> >http://blog.csdn.net/whinah/archive/2010/08/05/5791255.aspx
>
> > Blog:http://www.cnblogs.com/baiyanhuang/
> > Douban:http://www.douban.com/people/baiyanhuang/
>
> > 2011/4/3 Shuo Chen <giantc...@gmail.com>
On Apr 3, 1:28 pm, lzprgmr <baiyanhu...@gmail.com> wrote:
> >>你想问什么?
>
> 我主要是考虑assert的效率,在验证一个序列的属性时,可能需要线性的复杂度,如验证输入序列是否有序,或者验证某有序序列是否有相邻元素相等,这可能会对 调试版本的速度有很大的影响,尤其在输入有多个序列的时候。
>
> >>1. O(n) 太慢?"一个序列是否有重复,或者是否有序" 没有 o(n) 的算法吧?
>
> 验证一个序列是否有序是O(n)吧,"一个序列是否有重复"是我没说清楚,是指你这里用的adjacent_find
>
> >>2. adjacent_find 一般用不用? 如果正好适用,就代替手写循环呗。
>
> 所以你的回答是会对序列进行assert?
>
> >>3. assert 一般用不用? 不会用,除非在程序启动阶段。
>
> 这句什么意思?
>
> Blog:http://www.cnblogs.com/baiyanhuang/
> Douban:http://www.douban.com/people/baiyanhuang/
>
> 2011/4/3 Shuo Chen <giantc...@gmail.com>
这样的数据结构,占用的空间,查找的速度都会快一些,维护数据库也比较容易,找到相应的地方插入就行。
而且,考虑到最极端的情况,每个ip一个地址,读入到容器内处理感觉很困难。
另外,我实在受不了map的实现,有序序列的查找,感觉怎么也应该是线型的数据结构。
在这里看到一道面试题:
http://blog.csdn.net/whinah/archive/2011/04/02/6299288.aspx
从一组 IP range --> value 的数据中查找单个 IP,允许使用 C++ STL。
我的解法:
每个 range 的表示是三元组:(start ip, end ip, value)
按照你的思路,Binary search tree 的查找操作的时间复杂度是Ω(N),因为生成一个 N 节点的 bst 至少要线性时间。