【发布时间】:2017-10-24 08:09:57
【问题描述】:
pl 建议一个合适的数据结构来实现一个电话字典,它只有人名和电话号码。我可以考虑使用以名称为键、电话号码为值的哈希表。
但问题是我们无法根据电话号码搜索人名。 这可以假设所有名称都是唯一的。
~阿什
【问题讨论】:
-
两个哈希表,不是吗?
pl 建议一个合适的数据结构来实现一个电话字典,它只有人名和电话号码。我可以考虑使用以名称为键、电话号码为值的哈希表。
但问题是我们无法根据电话号码搜索人名。 这可以假设所有名称都是唯一的。
~阿什
【问题讨论】:
可能由一对尝试组成的数据结构可能会很好地工作。一个尝试会给你一个电话号码和一个名字,另一个会给你一个电话号码的名字。
为您提供姓名电话号码的树的节点将具有用构成姓名的符号标记的边缘。与每个顶点关联的值将指向另一个树中的节点(为您提供电话号码名称的那个),该节点对应于姓名从根到顶点的人的电话号码。给定一个名称,您可以返回具有该名称的人的相应电话号码(通过从链接节点遍历到根节点)。实际上,您可以使用它来查找姓名以某个前缀开头的所有人员及其对应的电话号码。
以下是姓名到电话号码的示例:
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的路上找到C、B和A,一路上的数字是3、2和1。通过按照回溯期间看到的顺序连接它们,然后反转该连接,我们获得了从A 到D 的字符串,因此对应于JASO:123。 JASON 也是如此。
添加新条目意味着同时向两个尝试添加一个条目,然后链接它们。如果允许重复的名称或数字,则可以引用节点集合,而不是指向另一个 trie 中的一个节点。删除一个条目意味着简单地从每棵树中删除相应的节点。有效名称是引用了电话号码的名称。有效的电话号码是指姓名的电话号码。
【讨论】:
使用 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"));
【讨论】:
选择数据结构取决于可用资源,即时间和空间(处理器和内存),在我们这个时代,高规格的硬件是主要的,所以如果你瞄准好的规格,我建议你通过实现一个链表,每个节点包含名称和编号,然后实现两个功能,一个用于名称搜索,一个用于数字,还可以对名称进行排序以在搜索名称时使用二进制搜索。
请注意,Worst case 代表 Access 和 Search 代表链表,O(n) 代表时间,O(n) 代表空间,这对于好的规格硬件来说是相当不错的,有关时间和空间复杂性的更多详细信息对于常见的数据结构,请参阅Link,以便比较并选择适合您要求的数据结构。
【讨论】: