我有一份国家名单,我希望拥有最长的国家道路,每个国家的选择必须以结束前一个元素的相同字母开头
nations = ['albania','andorra','austria','belarus','belgium','bosnia and herzegovina',
'bulgaria','croatia','czech republic','denmark','estonia',
'finland','france','germany','greece','hungary',
'iceland','ireland','italy','latvia','liechtenstein','lithuania','luxembourg',
'macedonia','malta','moldova','monaco','montenegro','netherlands',
'norway','poland','portugal','romania','russia',
'san marino','serbia','slovakia','slovenia','spain','sweden', 'switzerland',
'ukraine','united kingdom','vatican city']
chain('spain')
>>>['spain', 'netherlands', 'slovenia', 'andorra', 'austria', 'albania']
我试过这种方式,但它不起作用
def chain(naz):
initial = naz[-1]
initials=[]
res = set()
res.add(naz)
for i in nations:
if i.startswith(initial):
initials.append(i)
for j in initials:
nations.remove(j)
res.add(j)
chain(j)
return res
有什么建议吗?
答案 0 :(得分:5)
以下是一些评论:
while
某处i.startswith(initial)
才是真的。你可能不想要这个nations
是一个全局变量,很糟糕修改的
您的评论中描述的错误可能会发生,因为您的重复调用是在j循环中。重复呼叫可以删除国家的元素,这些元素也可能存在于首字母中。所以你试图不止一次地删除它们,这引起了一个例外。你可能想把chain(j)
放在循环之外(并且可能使用它的返回值?)
答案 1 :(得分:5)
我也去了递归下降。不确定动态编程是否适合这种情况,因为列表会随着我们的进行修改。在调用链之前,稍微更紧凑并且不需要从列表中删除。 : - )
def chain(start, countries):
remaining = list(countries)
del remaining[remaining.index(start)]
possibles = [x for x in remaining if x[:1] == start[-1:]]
maxchain = []
for c in possibles:
l = chain(c, remaining)
if len(l) > len(maxchain):
maxchain = l
return [start] + maxchain
这样打电话。 : - )
>>> chain('spain', nations)
['spain', 'netherlands', 'serbia', 'albania', 'andorra', 'austria']
答案 2 :(得分:2)
作为旁注,你的问题是NP完全的(意味着它没有“快速”多项式时间解决方案。)它可以解决小问题,但很快就会变得非常困难。
您的问题可以被视为longest-path problem on a directed graph。
w1
和w2
,如果w1 -> w2
的最后一个字母与{{1}的第一个字母相同,则绘制边w1
}}。w2
的最后一个字母与w2->w1
的第一个字母相同,也会从w2
绘制反边。以下是水果和蔬菜列表的示例图:w1
。
此图表可能包含周期(例如,此图表有一个周期Apple, banana, eggplant, kiwifruit, orange, oregano, tangerine, zucchini
。The longest path problem for directed graphs containing cycles is NP-complete.因此,此问题没有多项式时间解决方案。
这并不意味着你不能比蛮力更好。 There's a dynamic programming algorithm将复杂性从eggplant -> tangerine -> eggplant -> tangerine....
(因子,非常坏)降低到O(n!)
(超指数,仍然很差,但比因子更好。)
答案 3 :(得分:1)
这是一种天真的递归方式......我觉得你可以使用动态编程,它会更好
def chain(start,options):
#start is the starting word
#options are the words left
next_options = [country for country in options if country[0] == start[-1]]
#if theres no options, return the single
if not next_options:
return [start]
#otherwise, return best chain out of the next option
best_chain = None
longest_chain = 0
for option in next_options:
new_options = options[:]
new_options.remove(option)
possible_chain = chain(option,new_options)
if len(possible_chain) > longest_chain:
best_chain = possible_chain
longest_chain = len(possible_chain)
return [start] + best_chain