【问题标题】:which data structure to use to implement phone book which can be searched either on Name or phone number? [duplicate]使用哪种数据结构来实现可以在姓名或电话号码上搜索的电话簿? [复制]
【发布时间】:2017-10-24 08:09:57
【问题描述】:

pl 建议一个合适的数据结构来实现一个电话字典,它只有人名和电话号码。我可以考虑使用以名称为键、电话号码为值的哈希表。

但问题是我们无法根据电话号码搜索人名。 这可以假设所有名称都是唯一的。

~阿什

【问题讨论】:

  • 两个哈希表,不是吗?

标签: algorithm data-structures


【解决方案1】:

可能由一对尝试组成的数据结构可能会很好地工作。一个尝试会给你一个电话号码和一个名字,另一个会给你一个电话号码的名字。

为您提供姓名电话号码的树的节点将具有用构成姓名的符号标记的边缘。与每个顶点关联的值将指向另一个树中的节点(为您提供电话号码名称的那个),该节点对应于姓名从根到顶点的人的电话号码。给定一个名称,您可以返回具有该名称的人的相应电话号码(通过从链接节点遍历到根节点)。实际上,您可以使用它来查找姓名以某个前缀开头的所有人员及其对应的电话号码。

以下是姓名到电话号码的示例:

  J    A    C    K
1--->2--->3--->4--->5
     |    |
   I |  S V 
     |    9--->10--->11
     V      O     N
     6--->7--->8
       L    L

假设代表的人是 Jack、Jill、Jason 和 Jaso(一名外国交换生)。另一个尝试可能如下所示:

  1    2    3
A--->B--->C--->D
     |    |
   3 |    V 2
     |    E
     V 3
     F--->G
     |
   2 |
     V
     H

电话号码是 123、122、133 和 132。

现在,引用将如下所示:

Name Trie    Number Trie
---------    -----------
1->null      A->null
2->null      B->null
3->null      C->null
4->null      D->10
5->E         E->5
6->null      F->null
7->null      G->8
8->G         H->11
9->null
10->D
11->H

在名称trie 中输入JAS 后,我们可以很容易地确定该名称没有数字,因为节点9 没有对应的数字。假设我们想列出名字以这种方式开头的人的所有数字。我们可以使用您喜欢的任何方法遍历树(基于字母顺序的中序遍历看起来很合理)给出JASO (10)JASON (11),我们看到它们在电话号码树中有相应的节点。

对于这些节点中的每一个,我们都可以跳转到电话号码树并返回父节点(假设我们在每个节点中保存了父节点引用,这是可行的)。在此过程中,我们可以跟踪边缘标签以得出与我们的节点对应的数字。由于10->D,我们在返回根A的路上找到CBA,一路上的数字是321。通过按照回溯期间看到的顺序连接它们,然后反转该连接,我们获得了从AD 的字符串,因此对应于JASO123JASON 也是如此。

添加新条目意味着同时向两个尝试添加一个条目,然后链接它们。如果允许重复的名称或数字,则可以引用节点集合,而不是指向另一个 trie 中的一个节点。删除一个条目意味着简单地从每棵树中删除相应的节点。有效名称是引用了电话号码的名称。有效的电话号码是指姓名的电话号码。

【讨论】:

  • 虽然对于任何典型的 DS & Algo 相关问题都没有完美的答案,但我发现您的答案非常好,因为我们没有重复名称和数字所需的空间。一个 trie 专用于名称,另一个专用于数字,因此这里的空间复杂度肯定会降低,时间复杂度当然是 O(k),其中 K 是名称/电话号码的长度。
【解决方案2】:

如果你想快速浏览名称,你可以实现 Tries。

Tries 基本上是树,其中每个节点都连接到 n 个子节点,其中 n 是您可以想到的字符数(对于搜索字符串中的小字符,可以是 26,如果您认为大写和小写字母不同,则可以是 52,或者62 如果您也将数字带入索引,这一切都基于您对 Trie 的要求。

更多信息可以在here找到。

可以在here找到trie的示例实现:

尝试有效地用于进行部分字符串搜索。

搜索和插入的复杂性受限于被搜索词的长度O(length)

【讨论】:

    【解决方案3】:

    使用 Gauva Bimap 并反转它。

    BiMap<Integer, String> biMap = HashBiMap.create(); biMap.put(9856435634, "M"); biMap.put(9856435635, "S"); biMap.put(9856435636, "R");  System.out.println(biMap.inverse().get("M")); 
    

    【讨论】:

      【解决方案4】:

      选择数据结构取决于可用资源,即时间和空间(处理器和内存),在我们这个时代,高规格的硬件是主要的,所以如果你瞄准好的规格,我建议你通过实现一个链表,每个节点包含名称和编号,然后实现两个功能,一个用于名称搜索,一个用于数字,还可以对名称进行排序以在搜索名称时使用二进制搜索。

      请注意,Worst case 代表 AccessSearch 代表链表,O(n) 代表时间,O(n) 代表空间,这对于好的规格硬件来说是相当不错的,有关时间和空间复杂性的更多详细信息对于常见的数据结构,请参阅Link,以便比较并选择适合您要求的数据结构。

      【讨论】:

        猜你喜欢
        • 2012-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-22
        • 2021-05-14
        • 1970-01-01
        相关资源
        最近更新 更多