【问题标题】:Order a list of characters, given a dictionary给定字典,对字符列表进行排序
【发布时间】:2012-05-05 11:01:45
【问题描述】:

我在一次采访中被问到这个问题。假设你有一个有序的字典,并且给定了一个无序字符列表——你将如何按优先顺序排列这些字符?该词典包含保证出现所有 26 个字符的单词。但是,请注意字典的大小可能是任何值。字典可能只有几个单词,并且每个字符可能没有单独的部分,例如,可能没有以 a 开头的单词的部分;尽管a 将作为另一个单词的一部分出现,例如“bat”。

字典可能是“有序的”(/sarcasm),例如“zebra”、“apple”、“cat”、“crass”,如果给定列表 {a, z, @ 987654325@},正确的顺序是{@​​987654326@,a,r}。由于字典中“zebra”在“apple”之前,我们知道za之前。因为“apple”在“cat”之前,我们知道ac之前。因为“cat”在“crass”之前,我们知道ar之前。这个排序留下cr 存在不确定性,但由于字母列表是 {a, z, r},我们知道解决方案是 {z, a, r}。

【问题讨论】:

  • 给定一个字典,其中一些单词共享前缀,可能会得出正确的顺序("cat", "car" 可以看到t < r)。但是,给出的示例并非如此;我看不出他们从哪里得到了“r”的顺序。
  • @Emil 谢谢。我更新了这个例子,也许它更有意义。无论如何,我承认 - 这是一个非常奇怪的问题。
  • 我没有解决方案,但我有一个想法:从字典中,形成一个已知优先规则的列表。在给定的示例中,它们将是z<a, z<c, a<c, a<r。 (可选)添加z<r,因为优先级是可传递的。通过假设“X
  • 在您的问题陈述中,您应该包含一个测试用例,其中字母不是以字符开头并显示它是如何处理的。
  • 问题陈述中的测试用例确实包含一个没有单词开头的字母:r。除非你的意思是一个我们找到的字母都不是以开头的词,比如“猫”?

标签: java algorithm


【解决方案1】:

使用有 26 个顶点的有向图,每个顶点代表一个字符。从顶点 A 到顶点 B 的边意味着在字母表中 B 在 A 前面。

第一步是建立这样一个只有顶点没有边的图。

其次,您逐字扫描输入字典。并将每个单词与前一个单词进行比较。您应该为您扫描的每个单词找到一个确切的关​​系。所以你在这个图中添加了一条边。假设字典是正确的,应该没有冲突。

读完字典后,按

输出字母表
  1. 选择一个随机顶点,遍历它的路径,直到找到一个不指向任何东西的字符。这是字母表中的第一个字符。将其输出并从图中删除。
  2. 继续执行 1 直到所有顶点都被删除。

编辑: 为了更好地解释这个算法,让我们在您的示例输入上运行它。

输入:{“斑马”、“苹果”、“猫”、“粗鲁”}

单词0和单词1,我们马上就知道z在a之前,所以我们做一条边a->z

单词 1 和单词 2,我们立即知道 a 在 c 之前,所以我们再做一条边 c->a

Word 2 和 Word 3,第一个字母是相同的“c”,但第二个字母不同,所以我们知道 a 在 r 之前,所以我们有另一个边 r->a

现在所有的单词都读完了。通过随机选择一个顶点来输出顺序(比如我们选择 c),然后我们在图中有 c->a->z。输出 z 并从图中删除 z(将其标记为 NULL)。现在选择另一个(假设我们选择 r),然后我们在图中找到 r->a。我们输出 a 并从图中删除 a。现在我们选择另一个(假设我们再次选择 c),没有找到路径,所以我们只输出 c 并删除它。现在我们选择最后一个,r,又没有路径了,所以我们输出r并删除它。既然所有的顶点都被删除了,那么算法就完成了。

输出是z,a,c,r。 “c”和“r”的顺序是随机的,因为我们从输入中并不真正知道它们的关系。

【讨论】:

  • 除非我在这里遗漏了一些明显的东西,否则这种方法在很多方面都是矫枉过正的。即使在您似乎需要某种拓扑排序的最后两点,您也会继续造成更大的伤害。告诉我我错过了什么,我一定会向你道歉。但到目前为止,代码看起来像您对patience sorting 的回答
  • @kasavbere 我的算法在 O(N) 时间内解决了这个问题,N 是字典和 O(k^2) 空间的大小,k 是字母表的大小。我怀疑是否有更有效的方法来做到这一点。因此,我不明白你所说的过度杀伤或“继续造成更多伤害”是什么意思。最后两点是必要的,因为没有更好的方法来保证字母表中的“最后一个”字符。您能否更具体地阐述您的问题? (比如,算法的哪一部分效率不高)
  • @kasavere 不。边可以与字典提供的关系数量一样多,这肯定以 k^2 为界,k 是字母表的大小,正如我在之前的评论中所说的
  • @kasavbere 我同意可能有更好的算法可以使最终输出阶段更快一点,但考虑到字典的大小比字母表的大小要大得多,关键点这个问题的关键是如何有效而巧妙地从字典中提取字母之间的关系。同样,该解决方案给出了 O(N) 时间复杂度性能,这很可能是下限。
  • @kasavbere 您提供的示例字典无效
【解决方案2】:

根据“zebra”

我们可以在x < y 真值的二维数组中表示已知关系。

y\x a b c...r...z
a   -   N   N   Y
b     -
c   Y   -       Y
r   Y       -
z   N   N       -

蛮力方法是遍历输入列表中的所有字符对(即 {a, z, r} -> az, ar, zr)查找表中的a<za<r、@ 987654325@:如果这是错误的,那么交换字符并重新启动整个she-bang。当您完成整个过程而不必再交换任何字符时,输出将按照规则进行排序。这有点像做冒泡排序。

为了加快速度,我们可以更主动地在表格中填充隐含关系的单元格:例如,我们知道“z”z<a 和 z&lt;c) - 然后运行我们对 a 和 c 的了解。为避免树过深,您可以像这样只遵循一级间接,然后重复直到表稳定为止。

【讨论】:

  • 这与薛敬腾的回答非常相似,只是他展示了一种从网格中按顺序提取字母的快速方法,只需找到全为 Y 的行,然后删除该行/列。 (假设删除行/列很快)
  • @Mooing Duck:不一定会完全指定任何列或行...可能存在无法链接的不同部分排序。
【解决方案3】:

根据您描述问题的方式,您的示例不正确。你的答案应该是{z,r,a}。然而,这可能是,下面是解决问题的代码。您可以修改它以返回与我假设的 {z,r,a} 不同的订单。

Set<Character> charPrecedence(List<String> dictionary, char[] letters){
    Set<Character> result = new HashSet<Character>();
    //since your characters are the 26 letters instead of the 256 chars
    // a bit vector won't do; you need a map or set
    Set<Character> alphabets = new HashSet<Character>();
    for(char c: letters)
       alphabets.add(c);

    //now get to work
    for(String word: dictionary){
       if(alphabets.isEmpty()) return result;
       for(char c: word.toCharArray()){
          if(alphabets.remove(c))
           result.add(c);
       }
    }
    //since the dictionary is guaranteed to contain all the 26 letters,
    //per the problem statement, then at this point your work is done.
    return result;
}

最佳情况 O(1);最坏情况 O(n),其中 n 是字典中的字符数,即一个特定字母只出现一次,并且是您检查的最后一个字符。

【讨论】:

  • 样本正确。基本上,字典已经按照不是 ABCDEF 的字母顺序排序了...,我们必须弄清楚字母的顺序。
  • 它没有按 ABCDEF 排序是显而易见的。在你的问题陈述中,你应该包含一个字母不是单词开头的测试用例,并说明它是如何处理的。
  • @Mooing Duck 这么快就投了反对票,但你的回复毫无意义。你不是说apple 早于crass
  • 对不起,我的评论确实毫无意义。在他的示例中,a 出现在 r 之前,因为“cat”出现在“crass”之前。
  • @Mooing Duck,你又搞错了。看看理解这个问题有多难?所以这个问题真的很糟糕,我的解决方案完全有道理,这取决于我如何解释它——我在回复中声明了这一点。所以你不应该投反对票,我的朋友。
猜你喜欢
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多