Algorithm 采访中的问题,从字典中检索字母顺序

Algorithm 采访中的问题,从字典中检索字母顺序,algorithm,puzzle,graph-theory,topological-sort,Algorithm,Puzzle,Graph Theory,Topological Sort,我的女朋友在一次采访中得到了这个问题,我非常喜欢这个问题,我想我会分享它。。。 编写一个接收字典(单词数组)的算法。数组是按字典顺序排序的,但abc顺序可以是任意顺序。例如,它可以是z,y,x,…,c,b,a。或者它可能是完全混乱的:d,g,w,y。。。它甚至不需要包含所有的abc字母,最后它也不必是字母。它可以是构成字符串的任何符号。例如,它可以由5,α,!,@,θ... 你明白了。由您的算法来发现字母是什么(简单部分) 算法应该返回符号的正确字典顺序 注意/需要考虑的事项: 1.对于一本给定

我的女朋友在一次采访中得到了这个问题,我非常喜欢这个问题,我想我会分享它。。。 编写一个接收字典(单词数组)的算法。数组是按字典顺序排序的,但abc顺序可以是任意顺序。例如,它可以是z,y,x,…,c,b,a。或者它可能是完全混乱的:d,g,w,y。。。它甚至不需要包含所有的abc字母,最后它也不必是字母。它可以是构成字符串的任何符号。例如,它可以由5,α,!,@,θ... 你明白了。由您的算法来发现字母是什么(简单部分)

算法应该返回符号的正确字典顺序

注意/需要考虑的事项: 1.对于一本给定的字典,你总能找到所有字母的完整顺序吗?考虑一个只有1个单词,超过1个符号的字典… 2.你不能假定字典没有错误。算法应确定字典是否包含矛盾,并输出是否存在错误。 3.提示:考虑一个好的数据结构来表示符号之间的关系。这将使问题更容易解决

我可能明天会发布我的解决方案。我决不认为这是最有效的。我想先看看别人的想法。 希望你喜欢这个问题

附言。 我认为发布解决方案的最佳格式是使用伪代码,但我将此留给您考虑

这是一个很好的解决方案。您需要首先构建图形:顶点是字母,如果一个在字典上小于另一个,则有一条边。拓扑顺序会给你答案

矛盾是当有向图不是非循环图时。唯一性由哈密顿路径是否存在决定,哈密顿路径在多项式时间内是可测试的


构建图表 您可以通过比较字典中的两个连续“单词”来实现这一点。假设这两个词一个接一个出现:

x156@
x1$#2z
然后找到最长的公共前缀,
x1
(在本例中),并检查该前缀后面紧跟的字符。在本例中,我们有
5
$
。由于单词在词典中按此顺序出现,我们可以确定
5
在词典编纂上必须小于
$

同样,给出以下单词(在字典中一个接一个出现)

我们可以从第一对中看出
'j'<'1'
(其中最长的公共前缀是空字符串)。第二对没有告诉我们任何有用的信息(因为其中一个是另一个的前缀,所以没有要比较的字符)

现在假设稍后我们看到以下内容:

oi1019823
oij(*#@&$
foreach i = 1, m do
    foreach j = i + 1, m do
        findFirstDifferenceInTheWords
        /*charI is the first difference in Wi from Wj and charJ is the first difference in 
          Wj*/
        if (Wi <> Wj)
            if (Wi contains Wj or Wj contains Wi) == false
            charSet.add(charI, charJ)
        else if k exists and the following is true ((i < k < j) and (Wi <> Wk))
            error.addIfDoesntExist("paradox", Wi)
        else
            error.addIfDoesntExist("redundant", Wi)
        end_if
    end_foreach
end_foreach
然后我们发现了一个矛盾,因为这对表示
'1'<'j'


拓扑排序 进行拓扑排序有两种传统方法。算法上更简单的方法是,如果
y
,则存在从
x
y
的边缘

该算法的伪代码在维基百科中给出:

L ← Empty list that will contain the sorted nodes
S ← Set of all nodes with no incoming edges

function visit(node n)
    if n has not been visited yet then
        mark n as visited
        for each node m with an edge from n to m do
            visit(m)
        add n to L

for each node n in S do
    visit(n)
L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
    remove a node n from S
    insert n into L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S
if graph has edges then
    output error message (graph has at least one cycle)
else 
    output message (proposed topologically sorted order: L)
在上述算法结束后,列表
L
将按拓扑顺序包含顶点


检查唯一性 以下是维基百科的一段引文:

L ← Empty list that will contain the sorted nodes
S ← Set of all nodes with no incoming edges

function visit(node n)
    if n has not been visited yet then
        mark n as visited
        for each node m with an edge from n to m do
            visit(m)
        add n to L

for each node n in S do
    visit(n)
L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
    remove a node n from S
    insert n into L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S
if graph has edges then
    output error message (graph has at least one cycle)
else 
    output message (proposed topologically sorted order: L)
如果拓扑排序的属性是排序顺序中的所有连续顶点对都由边连接,则这些边在DAG中形成有向哈密顿路径。如果存在哈密顿路径,则拓扑排序顺序是唯一的;没有其他顺序考虑路径的边。相反,如果拓扑排序不形成哈密顿路径,则DAG将具有两个或多个有效拓扑排序,因为在这种情况下,始终可以通过交换两个未通过边相互连接的连续顶点来形成第二个有效排序。因此,可以在多项式时间内测试是否存在唯一的顺序,以及是否存在哈密顿路径

因此,要检查顺序是否唯一,只需检查
L
(来自上述算法)中的所有两个连续顶点是否通过直接边连接即可。如果是,则顺序是唯一的


复杂性分析 构建图形后,拓扑排序为
O(| V |+| E |)
。唯一性检查是
O(|V | edgeTest)
,其中
edgeTest
是测试两个顶点是否由一条边连接的复杂性。对于,这是
O(1)

构建图表只需要对字典进行一次线性扫描。如果有
W
单词,则是
O(W cmp)
,其中
cmp
是比较两个单词的复杂性。您总是比较后面的两个单词,因此可以在必要时进行各种优化,但在其他情况下,简单的比较是
O(L)
,其中
L
是单词的长度


一旦你确定你有足够的字母表等信息,你也可以缩短阅读字典的时间,但即使是一个简单的构建步骤也需要
O(WL)
,这是字典的大小。

你想要找到符号的总顺序

1) 显然,您可能无法始终确定总订单

2) 可以使用有向非循环图来表示符号之间的偏序。每个字母在图形中仅表示一次。 您可以通过查看每对连续单词中相同位置的所有字母对来填充它。在图形中创建的任何循环都指向字典中的错误。 您可以将一组关系(如a->d,a->b,b->d)展平为a->b->d。
如果你最后得到的是一个有一个源(没有前辈的字母)和一个汇(没有后继者的字母)的图形,你有一个总的顺序,就像字母表一样。

我用另一个解决了这个问题