我在Python中使用广度优先搜索算法来查找从三个字母单词到另一个单词的最短“路径”。我已经有了它的工作,但表现很糟糕,我怀疑我的单词生成功能。
基本上,对于我从队列中弹出的每个单词,我都会生成所有其他三个字母的单词,这些单词可以通过交换一个字母来形成。功能如下:
#Pseudo code
For each position (1-3)
For each letter (a-z)
create a new word by exchanging the letter at the position
if this word is a valid word and is not used earlier
add it to the return list
return the list
这通常需要大约0.03秒。 有更快的方法吗?
答案 0 :(得分:4)
我假设您有一个有效单词列表,并且您实际上并不是在寻找单一路径(为什么要关注优化),而是考虑很多路径。使用networkX:
可以非常轻松地完成此操作from networkx import Graph
from networkx.algorithms.shortest_paths import shortest_path, all_pairs_shortest_path
from itertools import combinations
WORDS = {'cat', 'hat', 'sat', 'car', 'cad', 'had', 'pad', 'pat', 'can', 'man'}
def makeGraph(words):
""" create a graph where nodes are words and two words are
connected iff they have one different letter """
G = Graph()
# all word combinations
for a,b in combinations(WORDS,2):
# number of different letters
diff = sum(1 for x,y in zip(a,b) if x!=y)
if diff == 1:
G.add_edge(a,b)
return G
g = makeGraph(WORDS)
# path between two words
print shortest_path(g, 'cat', 'pad')
# generating all shortest paths is way more efficient if you want many paths
paths = all_pairs_shortest_path(g)
print paths['cat']['pad']
感谢@Ducan的示例单词。
如果你真的想自己实现这些算法,你可以在wikipedia找到大量的描述。经典的单源最短路径算法为Dijkstra's,经典的所有对最短路径算法为Floyd-Warshall。
答案 1 :(得分:2)
如果你想重新发明轮子,也许这会有所帮助(N.B.这已经设置了文字所以至少需要Python 2.7):
from collections import defaultdict
WORDS = {'cat', 'hat', 'sat', 'car', 'cad', 'had', 'pad', 'pat', 'can', 'man'}
D1 = defaultdict(set)
D2 = defaultdict(set)
D3 = defaultdict(set)
for w in WORDS:
D1[w[:2]].add(w)
D2[w[0]+w[2]].add(w)
D3[w[1:]].add(w)
def follows(w):
followers = set(D1.get(w[:2]).union(D2.get(w[0]+w[2]), D3.get(w[1:])))
followers.discard(w)
return followers
for w in WORDS:
print(w, follows(w))
答案 2 :(得分:0)
不要以次优的方式重新发明轮子:使用现有的模块: