Data structures 电话簿的一种数据结构,它可以按姓名搜索号码,也可以按号码搜索姓名

Data structures 电话簿的一种数据结构,它可以按姓名搜索号码,也可以按号码搜索姓名,data-structures,hash,dictionary,hashmap,Data Structures,Hash,Dictionary,Hashmap,你知道以下面试问题的答案吗 为电话簿设计一个数据结构,该结构可以安全、高效地 高效地按名称搜索数字,也按数字搜索名称 详情: stackoverflow上的解决方案都是关于哈希表的,但是,我必须为此构建2个哈希表,这需要两倍的空间 如何以节省时间和空间、类型安全的方式仅使用一个数据结构?将所有内容(即两个方向)散列到同一个表中。这不是很容易吗 使用值对(电话号码、名称)的记录/结构/元组数组 进行线性搜索,查找搜索关键字;O(n/2)表示匹配, O(n)代表小姐 返回record/struct

你知道以下面试问题的答案吗

为电话簿设计一个数据结构,该结构可以安全、高效地 高效地按名称搜索数字,也按数字搜索名称


详情:

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

如何以节省时间和空间、类型安全的方式仅使用一个数据结构?将所有内容(即两个方向)散列到同一个表中。

这不是很容易吗

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

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

  • 返回record/struct/tuple并执行任何需要执行的操作

  • 编辑:
    该算法可以在许多方面进行改进

    我认为这个面试问题可能是故意少提,以了解受访者的反应。(这就是我面试时做的事情)。因此,更重要的是将其视为一个问题,而不是假设它只是一个计算机科学问题

    我认为与面试官接触是值得的。例如:

  • 对于个人电话簿,例如移动电话上的个人电话簿(任何合理的算法都不太可能太慢),或者对于可能存在可用性、并发更新和额外要求的国家规模的电信基础设施应用程序,这是否重要,例如,对某些名称和数字子集的访问控制
  • 目标技术是什么?您可能需要选择不同的方法,例如Python、C++、汇编程序……/LI>。
  • 他们需要展示的品质是否比时空效率更高?例如,证明正确或测试是否容易?通过快速方法节省的CPU值不值得人为花费测试时间
  • 维护和重用代码的人员可能有多熟练或知识渊博?从维护成本的角度考虑,是否倾向于采用简单的方法
  • 等等


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

    这种数据结构称为多索引容器。它们在大多数编程语言中并不常见,因为接口可能变得相当复杂。 在Boost库中有,而且最突出的是C++,尤其是关于<强>双向映射< /强>:

    双向映射是(const FromType,const ToType)对的容器,因此 两个元素具有相同的第一个或第二个组件(std::map 仅保证第一个组件的唯一性)。快速查找是必要的 两把钥匙都有。这个节目的特色是一个小小的西班牙语和英语 在线查询两种语言单词的词典


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

    很好。。我同意多重索引,这是正确的方法。然而,对于工作面试,他们可能希望你思考并解释一些事情,而不仅仅是说使用boost。如果他们问起boost的内部结构,如果你不能正确解释的话,那可能会很尴尬

    因此,这里有一个可能的解决方案

    首先,不要为此使用哈希表。电话和姓名可以很容易地分类,你可能应该使用一些平衡的搜索树,如果你想进行交互式搜索,也可以使用trie(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; 
    
    祝您好运

    您可以使用36元树(26元代表字母,10元代表数字),并具有从字母和数字指向同一节点的链接。(严格来说,这不是一棵“树”,但你明白了)。这样,您将不会得到一个固定时间的查找,但您不必重复数据,而且查找速度仍然非常快

    当然,您必须处理冲突,但也必须在使用哈希表时处理冲突。
    也许您可以使用两个指针按名称和编号指向下一个发生冲突的节点。

    @user1002288:在number->name的情况下,键就是编号。在name->number的情况下,关键是name.Oli,所以实际上,您需要构建两个哈希表并将它们放在一个哈希表中,第一部分是name->number,第二部分是number->name,对吗?@user1002288:不,您只需要一个(假设没有人拥有名称
    555-6253
    )。但是,只有一个并没有真正的优势,所以我不确定这个问题的目的是什么……假设给定:Jack-->123,Tom-->456,如果我们使用name作为键,如何搜索给定名称的数字?e、 如何找到汤姆?谢谢@user1002288:对于每个名称-数字对,将{key=name,value=number}和{key=number,value=name}都放入表中。您在寻找哪种解决方案?具体来说,为什么我的答案是“不是解决方案”?很有趣,那些多索引容器(+1)。所以在con之间有一对一的映射
    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();
    }