电话簿的数据结构,可以按名称搜索号码,也可以按号码搜索姓名

时间:2012-04-01 16:48:32

标签: data-structures hash dictionary hashmap

您是否知道以下面试问题的解决方案?

  

为电话簿设计一个安全可靠的数据结构   有效地按名称搜索数字,并按编号搜索名称。


详细说明:

在stackoverflow上找到的解决方案都是关于哈希表的,但是,我必须为它构建2个哈希表,这需要两倍的空间。

如何以时间和空间效率,类型安全的方式只使用一个数据结构?

5 个答案:

答案 0 :(得分:16)

此类数据结构称为多索引容器。它们在大多数编程语言中并不常见,因为界面可能变得非常复杂。 JavaC#和 - 最突出的是 - 使用Boost库的C ++实现,请参阅Boost.MultiIndex Documentation,特别是example 4关于双向地图

  

双向映射是(const FromType,const ToType)对的容器,不是   两个元素存在相同的第一个或第二个组件(std :: map   只保证第一个组件的唯一性)。快速查找是   提供两个键。该计划有一个小西班牙语 - 英语   在线查询两种语言的单词字典。

多索引容器的基本思想是许多容器将其元素存储在包含指向其他节点的指针/引用的节点中(例如双链表)。节点包含多个索引结构的链接,而不是仅存储单个容器的指针/引用。这至少适用于链表,排序树和唯一哈希索引。并且实现非常有效,因为每个元素只需要一次内存分配。

答案 1 :(得分:4)

嗯..我同意多索引,这是正确的方法。然而,对于求职面试,他们可能希望你考虑并解释一些事情,而不仅仅是说使用提升。如果他们询问提升的内部因素,如果你无法正确解释它可能会令人尴尬。

所以,这是一个可能的解决方案。

首先,不要使用散列表。手机和名称可以轻松排序,您应该使用一些平衡的搜索树,或者如果您想要交互式搜索(http://en.wikipedia.org/wiki/Trie)。恕我直言,哈希表在这种情况下是一个很大的浪费空间。

让我们假设名称是唯一的,数字是唯一的。然后,你可以这样做:

1-保存数据的数据结构

struct Phone {
 // implement the phone here whatever they need
 // assume that whatever representation used can be converted into a unique id (number)
}; //
struct PhoneBookEntry {
   std::string name;
   Phone number;
}; 

2-创建两个树,一个用于名称,另一个用于电话

BalancedSearchTree<PhoneBookEntry> tree_by_name;
BalancedSearchTree<PhoneBookEntry> tree_by_number; 

3-就是这样。查找每棵树,无论您需要什么

bool PhoneBook::getByName(const std::string &name, PhoneBookEntry &o) {
  tree_by_name.get(name, o);
  return !o.empty();
}
bool PhoneBook::getByNumber(const Phone &p, PhoneBookEntry &o) {
 tree_by_number.get(p, o);
 return !o.empty();
}
祝你好运

答案 2 :(得分:3)

将所有内容(即两个方向)散列到同一个表格中。

答案 3 :(得分:1)

这不容易吗?

使用值对的记录/结构/元组数组(电话号码,名称)。

  1. 进行线性搜索以查找搜索关键字; O(n / 2)匹配, O(n)代表小姐,

  2. 返回记录/结构/元组并做任何需要做的事情。

  3. 编辑:
    该算法可以通过多种方式进行改进。

    我认为这个面试问题可能是故意指定的,以便了解受访者的反应。 (这是我采访时的表现)。因此,对它进行处理可能更重要,而不是假设它只是一个计算机科学问题。

    我认为值得与面试官交流。例如:

    1. 这对于个人电话簿来说是否足够快是重要的,例如在移动电话上(不太可能是任何合理的算法太慢),或者是国家级电信基础设施应用,其中可能存在可用性,并发更新和额外要求,例如对某些名称和数字子集的访问控制?
    2. 目标技术是什么?您可能想要选择不同的方法,例如for Python,C ++,assembler,...
    3. 他们需要表现出的品质比时间和品质更高空间效率?例如,是否必须容易证明正确或测试?通过快速方法节省CPU是否值得花费人力测试时间?
    4. 人们维护和重用代码的技能或知识水平如何?在维护成本方面,是否会采用简单的方法。
    5. 等。

      我认为与面试官交往更重要,而不是只关注技术解决方案。当我采访时,我正在寻找一个试图真正理解整个问题的人,而不是那些容易定义的(通常很小的)部分。

答案 4 :(得分:0)

您可以使用36-ary树(26个用于字母表,10个用于数字),并且具有从字母表和数字指向同一节点的链接。 (严格来说,这不是一个“树”,但你明白了)。这样你就不会得到一个恒定的时间查找,但你不必重复数据,查找仍然会很快。

当然,你必须处理冲突,但是你也必须在使用哈希表时处理它们。 也许您可以使用两个指针按名称和数字指向下一个碰撞节点。