确切的问题陈述是这样的:给定根据一些未知的字母排序排序的单词字典,确定字母的总顺序。保证所提供的任何输入都具有总订单并且可以找到订单。
从我读到的关于这类问题的内容来看,解决这个问题的正确方法似乎是建立一个有向无环图,然后在图上进行拓扑排序。此外,有两种方法可以实现拓扑排序(我知道)。其中一个使用深度优先搜索,这就是我选择实现算法的方式。
我的程序适用于提供的少量测试用例(以及我能提出的任何测试用例),但是用于验证程序正确性的测试用例失败了。不幸的是,我无法访问这些测试用例,或者我可以更轻松地调试我的程序。
有人愿意建议对我的代码进行一些改进吗?有没有其他方法来解决这个问题?此外,是否有人知道生成良好测试用例的方法?我提出的测试用例不足以找到我的程序不正确的地方。一个理想的测试用例是一个单词词典,保证总排序存在并且可以获得。
我认为问题在于我构建有向无环图的方式。
from sets import Set
from copy import copy
#Hash table representation of directed acyclic graph.
DAG = {}
#Set of all vertices with no incoming edges
noIncomingEdges = Set()
#Any array (initially empty) which will contain the total order
#of the letters used to sort the dictionary
sortedLetters = []
class VertexList:
def __init__(self):
self.outgoing = Set()
def addOutgoingEdge(self, edge):
self.outgoing.add(edge)
def removeOutgoingEdge(self, edge):
self.outgoing.remove(edge)
def buildDAG(words):
numWords = len(words)
for i in range(numWords - 1):
#Get two consecutive words from the dictionary
w1 = words[i]
w2 = words[i + 1]
lenw1 = len(w1)
lenw2 = len(w2)
#If the first word is longer than the second, pad the first words
#by taking the last letter in the first words and appending it until
#both words are of equal length.
#As an example:
# a --> aa
# ab --> ab
#The algorithm for building the DAG should now be able to see that
#a comes before b.
if lenw1 < lenw2:
while len(w1) < lenw2:
w1 = w1 + w1[lenw1 - 1]
n = lenw2
for j in range(n):
#If the DAG doesn't have a vertex for a given letter, add it.
#Also, add it to the list of nodes with no incoming edges.
if not DAG.has_key(w1[j]):
DAG[w1[j]] = VertexList()
noIncomingEdges.add(w1[j])
if not DAG.has_key(w2[j]):
DAG[w2[j]] = VertexList()
noIncomingEdges.add(w2[j])
#Compare corresponding letters in the two consecutive words. If
#The letter in the first word is different from the letter in the
#second word, create an edge between the vertex represent the letter
#from the first word and the vertex for the letter in the second
#word.
if w1[j] != w2[j] and w2[j] not in DAG[w1[j]].outgoing:
DAG[w1[j]].addOutgoingEdge(w2[j])
#Remove the vertex for the second letter from the list of
#vertices with no incoming edges.
if w2[j] in noIncomingEdges:
noIncomingEdges.remove(w2[j])
break
def visit(v):
visited = Set()
if v not in visited:
visited.add(v)
vertices = copy.deepcopy(DAG[v])
for vertex in vertices.outgoing:
visit(vertex)
sortedLetters.insert(0, v)
def topologicalSort():
for vertex in noIncomingEdges:
visit(vertex)
def answer(words):
buildDAG(words)
topologicalSort()
return ''.join(sortedLetters)
答案 0 :(得分:0)
我发现了问题。它在行
if word1[j] != word2[j] and word2[j] not in DAG[word1[j]].outgoing:
你需要分开这些子句,因为当两个字母不同时你必须突破循环,即使DAG中的第二个字母是。否则,当你应该比较这些词时,你会继续下一对字母。
结果是你在这对单词中得到了一个虚假的DAG边缘。我用
开始了我的数据集a
ab
bad
第一次比较很顺利,向DAG添加了a-> b。 在第二次比较中, ab vs bad ,我们在第一个字母上找到了第一个差异。但是,由于b已经在a的传出列表中,因此您的逻辑表示继续执行下一个字母对。这会从第二个字母添加边b-> a。
这为DAG引入了一个循环,杀死了算法。代码应该是
if word1[j] != word2[j]:
if word2[j] not in DAG[word1[j]].outgoing:
<add edge>
break