最近我正在浏览一些面试问题,并发现了一些有趣的问题:
您将获得一个单词列表。找出两个单词是否可以连接 - 聚集形成回文。例如,考虑一个列表{bat,tab,cat}然后可以将bat和tab连接起来形成一个回文。 期待一个O(nk)解决方案,其中n =工作数,k是长度
可以有多对,只要找到它就返回true。
此外,在评论中,其中一种方法是:
1)将第一个单词添加到trie(A B)
2)取第二个字(D E E D B A)并将其反转(A B D E E D)
3)查看在trie中可以匹配的反向字中有多少个字母(前2个)
4)取其余的绳子(D E E D)看它是否是回文如果是你完成则返回true
5)将第二个单词添加到trie(D E E D B A)
6)用下一个单词回到步骤2
7)当单词返回false时
但在我看来,这不是O(nk)解决方案。
有人可以提出解决方案吗?或者解释为什么上述算法是O(nk)??
答案 0 :(得分:2)
算法是正确的,或者至少它非常接近。有一些小技术问题。在第4步中,如果解决方案比当前解决方案更好,那么应该保存解决方案的命题,并且在步骤7中,应该保留解决方案的命题,或者说它不可能成为回文。
主要思想是将单词处理为核心和前缀。如果核心是回文,那么我们需要将前缀与其他单词匹配。 Trie是一个数据库"对于已处理的字符串,因此对于每个新单词,可以检查所有可能的扩展名。如果单词保持单独,则需要分别比较每个单词的前缀。
(编辑:我认为仍然存在一个小漏洞,如果一个trie中有两个单词开始相同,并且即将进入的单词会与较短的单词形成回文,但不会更长,但我不会详细说明。处理它会使算法复杂化,但不会影响复杂性。)
它也是O(n*k)
。添加和检查前缀vs trie需要与字符数成比例的步数。所以在这种情况下,它受k
的约束。就像树操作O(h)
一样,其中h
是树的高度。总之:
k
步骤。
需要k
步。
最多只需k
步。
也需要少于k
个步骤,但我们可以k
限制它。
也需要k
步。
步骤2到5完成n-1
次。
当然每个步骤都有不同的显性操作,因此很难指定确切的常量,但所有这些都被k
约束,因此复杂度为O(c*(n-1)*k)
,基本上为{{1} }}
答案 1 :(得分:0)
2004年,Dr. Dobbs的一篇文章对此进行了非常有趣的讨论。完整的解释有点长,但总体思路是:
假设您从Lion开始,其中枢轴是实际单词的左侧。我可以计算出弦的中心,即位置2。枢轴为零,因此右侧的弦太重,但此刻,Lion有资格作为部分回文。枢轴点处的“点”与枢轴点处的点匹配,因此至少有一个正确的字符,尽管是相同的字符。您现在希望添加以落棉结尾的单词,尝试将字符串转换为noil.Lion。我用来表示任何字符串。如果您成功了,那么您需要找到以字母开头的单词,以便将它们附加到字符串中。
请注意,他将部分回文定义为:
如果从枢轴点向外工作,字符串是部分回文,则在发生不匹配之前遇到字符串的左端或右端。