Chris 的答案在列表 [9,10,9] 上失败,产生 10 而不是 9+9 = 18。
乔不太对劲。旅行推销员要求您访问每个城市,而这里没有类似的。
一种可能的解决方案是递归解决方案:
function Max_route(A)
if A's length = 1
A[0]
else
maximum of
A[0]+Max_route(A[2...])
Max_route[1...]
这与简单的斐波那契函数具有相同的大 O,如果您除了简单地获得正确答案之外还关心效率,那么它应该会产生一些相同的优化(例如记忆化)。
-- MarkusQ
[编辑] ---
因为有些人似乎没有明白这一点,所以我想解释一下我所说的记忆是什么意思以及它为什么重要。
您可以包装上面的函数,以便它只计算每个数组的值一次(第一次调用它),并且在后续调用中将简单地返回保存的结果。这将占用 O(n) 空间,但会在恒定时间内返回。这意味着整个算法将在 O(n) 时间内返回,比上面不太混乱的版本的指数时间要好。我假设这很好理解。
[二次编辑]------------------------------
如果我们稍微扩展一下上面的内容并将其分开,我们会得到:
f [] :- [],0
f [x] :- [x],x
f [a,b] :- if a > b then [a],a else [b],b
f [a,b,t] :-
ft = f t
fbt = f [b|t]
if a + ft.sum > fbt.sum
[a|ft.path],a+ft.sum
else
fbt
我们可以仅使用大小为 n 的整数和布尔数组以及以下操作展开为伪基础:1) 数组索引和索引数组赋值,2) 整数数学,包括比较,3) if/then/else,和 4) 一个 O(n) 的单循环:
dim max_sum_for_initial[n],next_to_get_max_of_initial[n],use_last_of_initial[n]
max_sum_for_initial[0] = 0
next_to_get_max_of_initial[0] = -1
use_last_of_initial[0] = false
max_sum_for_initial[1] = a[0]
next_to_get_max_of_initial[1] = -1
use_last_of_initial[1] = true
if a[0] > a[1]
max_sum_for_initial[2] = a[0]
next_to_get_max_of_initial[2] = 0
use_last_of_initial[2] = false
else
max_sum_for_initial[2] = a[1]
next_to_get_max_of_initial[1] = -1
use_last_of_initial[2] = true
for i from 3 to n
if a[i]+max_sum_for_initial[i-2] > max_sum_for_initial[i-1]
max_sum_for_initial[i] = a[i]+max_sum_for_initial[i-2]
next_to_get_max_of_initial[i] = i-2
use_last_of_initial[i] = true
else
max_sum_for_initial[i] = max+sum_for_initial[i-1]
next_to_get_max_of_initial[i] = i-1
use_last_of_initial[i] = false
最后我们可以提取结果(以相反的顺序):
for i = n; i >= 0; i = next_to_get_max_of_initial[i]
if use_last_of_initial[i] then print a[i]
请注意,我们刚刚手动执行的操作是现代语言的优秀编译器应该能够通过尾递归、记忆等来完成的。
我希望这已经足够清楚了。
-- MarkusQ
是 O(n)。