【问题标题】:Given a flat file of IP Ranges and mappings, find a city given an IP给定一个 IP 范围和映射的平面文件,找到一个给定 IP 的城市
【发布时间】:2012-03-23 13:52:04
【问题描述】:

这是问题:

给定一个包含映射的 IP 地址范围的纯文本文件 到一个位置(例如 192.168.0.0-192.168.0.255 = Boston, MA),提出一个算法,如果存在映射,该算法将为特定 IP 地址找到一个城市。

我唯一的想法是解析文件,然后将 IP 范围转换为整数(如果缺少数字,则乘以 10/100)并将它们放在一个列表中,同时将较低的范围放入哈希中作为以位置为值的键。对列表进行排序并执行稍微修改的二进制搜索。如果索引为奇数,则为 -1 并查看哈希。如果是偶数,只需查看哈希。

我的计划有什么错误,或者更好的解决方案?

【问题讨论】:

  • 如果您确信,请随时接受答案。如果您找到更好的答案,以后可以撤消此操作:-)

标签: algorithm search data-structures


【解决方案1】:

在您的示例中,192.168.0.0-192.168.0.255 = 马萨诸塞州波士顿。

对于条目中的两个 IP 地址,前三个八位位组 (192.168.0) 是否相同? 另外,前三个八位字节对于一个城市来说是独一无二的吗?

如果是这样,那么这个问题就更容易解决了

【讨论】:

  • 不确定。这是我在网上找到的一个面试题。
【解决方案2】:

您的方法似乎非常合理。

如果您有兴趣做一些研究/额外的编码,有些算法会渐近优于标准二进制搜索技术,该技术依赖于您的 IP 地址可以解释为 0 到 2 范围内的整数这一事实31 - 1. 例如,van Emde Boas treey-Fast Trie 数据结构可以在 O(log log U) 时间内实现您正在查看的前驱搜索操作,其中 U 是最大值可能的 IP 地址,而不是二进制搜索使用的 O(log N) 方法。但是,常数因子更高,这意味着不能保证这种方法会更快。但是,作为另一种可能更快的方法可能值得探索。

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    这个问题有范围的味道,解决这个问题的一个好的数据结构是段树。 Someresources 帮助您入门。

    段树的根可以表示地址(0.0.0.0 - 255.255.255.255)。左子树将表示地址 (0.0.0.0 - 127.255.255.255),右子树将表示范围 (128.0.0.0 - 255.255.255.255),依此类推。这将一直持续到我们达到无法进一步细分的范围。比如说,如果我们有 32.0.0.0 - 63.255.255.255 的范围,映射到某个任意城市,它将是一个叶节点,当我们到达那里时,我们不会进一步细分该范围,并将其标记为特定城市。

    要搜索特定的映射,我们会跟随树,就像我们在二叉搜索树中所做的那样。如果你的IP在左子树的范围内,移动到左子树,否则移动到右子树。

    好的部分:

    1. 您不需要拥有所有子树,只需添加所需的子树即可。例如,如果在您的数据中,没有为范围 (0.0.0.0 - 127.255.255.255) 映射的城市,我们将不会构建该子树。
    2. 我们节省空间。如果整个范围映射到一个城市,我们将只创建根节点!
    3. 这是一个动态数据结构。您可以稍后添加更多城市、拆分范围等。
    4. 您将进行恒定数量的操作,因为树的最大深度将是 4 x log2(256) = 32。对于这个特殊问题,事实证明分段树将 与 van- 一样快Emde Boas 树,并且需要更少的空间 (O(N))。
    5. 这是一个简单但重要的数据结构,它比排序更好,因为它是动态的,并且比 van-Emde Boas 树更容易向面试官解释。
    6. 这是最容易编码的重要数据结构之一 :)

    请注意,在某些 Segment Tree 教程中,它们使用数组来表示树。这可能不是您想要的,因为我们不会填充整个树,所以动态分配节点,就像我们在标准二叉树中所做的那样是最好的。

    【讨论】:

    • 由于范围不重叠,这里的分段树不是矫枉过正吗?我的理解是,当范围可能重叠时,段树是好的,但我想在这种特殊情况下没有任何重叠。
    • 我不确定是否收到您的评论。这可能是因为 Segment Tree 中的范围与我们想要存储的内容混淆了。我们要存储 IP 地址范围,我们称它们为值。现在,这些值不会重叠。但是值的范围确实重叠,例如,(0.0.0.0 - 255.255.255.255)是根节点,所有值都在这个范围内。
    【解决方案4】:

    我唯一的想法是解析文件,并将 IP 范围转换为整数(如果缺少数字,则乘以 10/100)...

    如果采用这种方法,您可能希望将地址 A.B.C.D 中的 A、B、C 和 D 分别乘以 256^3、256^2、256 和 1。这有效地将 IP 地址重新创建为 32 位无符号数。

    ... 并将它们放在一个列表中,同时将较低的范围作为键放入散列中,并将位置作为值。对列表进行排序并执行稍微修改的二进制搜索。如果索引为奇数,则为 -1 并查看哈希。如果是偶数,只需查看哈希。

    我建议创建一个连续数组(std::vector),其中包含具有上下范围(以及位置名称 - 下文讨论)的结构。然后,正如您所说,您可以对包含特定值的范围进行二分搜索,而不会遇到任何奇数/偶数的麻烦。

    使用范围的低端作为哈希中的键是避免在数组中为位置名称留出空间的一种方法,但考虑到城市名称中的平均字符数,指针的可能大小,a在稀疏填充的哈希表和冗长的位移列表之间进行选择以在连续的替代存储桶中搜索或进一步间接到任意长度的容器 - 您需要非常不顾一切地尝试尝试。在第一种情况下,将位置存储在 struct 中与 IP 值范围一起似乎很好。

    或者,您可以基于例如创建一棵树。单独的 0-255 IP 值:树中的每个级别可以是用于直接索引的 256 个值的数组,也可以是填充值的排序数组。这可以减少您可能需要进行的 IP 值比较次数(O(log2N) 到 O(1))。

    【讨论】:

      猜你喜欢
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 2020-12-21
      • 2012-10-28
      相关资源
      最近更新 更多