您是否知道以下面试问题的解决方案?
为电话簿设计一个安全可靠的数据结构 有效地按名称搜索数字,并按编号搜索名称。
详细说明:
在stackoverflow上找到的解决方案都是关于哈希表的,但是,我必须为它构建2个哈希表,这需要两倍的空间。
如何以时间和空间效率,类型安全的方式只使用一个数据结构?
答案 0 :(得分:16)
此类数据结构称为多索引容器。它们在大多数编程语言中并不常见,因为界面可能变得非常复杂。 Java,C#和 - 最突出的是 - 使用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)
这不容易吗?
使用值对的记录/结构/元组数组(电话号码,名称)。
进行线性搜索以查找搜索关键字; O(n / 2)匹配, O(n)代表小姐,
返回记录/结构/元组并做任何需要做的事情。
编辑:
该算法可以通过多种方式进行改进。
我认为这个面试问题可能是故意指定的,以便了解受访者的反应。 (这是我采访时的表现)。因此,对它进行处理可能更重要,而不是假设它只是一个计算机科学问题。
我认为值得与面试官交流。例如:
等。
我认为与面试官交往更重要,而不是只关注技术解决方案。当我采访时,我正在寻找一个试图真正理解整个问题的人,而不是那些容易定义的(通常很小的)部分。
答案 4 :(得分:0)
您可以使用36-ary树(26个用于字母表,10个用于数字),并且具有从字母表和数字指向同一节点的链接。 (严格来说,这不是一个“树”,但你明白了)。这样你就不会得到一个恒定的时间查找,但你不必重复数据,查找仍然会很快。
当然,你必须处理冲突,但是你也必须在使用哈希表时处理它们。 也许您可以使用两个指针按名称和数字指向下一个碰撞节点。