Arrays 求正数数组的最大子序列的算法。捕获:不允许相邻元素
例如,给定Arrays 求正数数组的最大子序列的算法。捕获:不允许相邻元素,arrays,algorithm,Arrays,Algorithm,例如,给定 A = [1,51,3,1,100,199,3], maxSum = 51 + 1 + 199 = 251. 显然max(oddinexsum,evenIndexSum)不起作用 我面临的主要问题是,我无法为元素提出选择标准。 给定一个选择准则,拒绝准则是微不足道的 标准的最大子序列算法在这里似乎不适用。 我尝试过一种动态规划方法,但也没有想到。 我唯一能想到的方法就是使用遗传算法 你将如何处理这个问题 max(oddIndexSum、evenIndexSum)不起作用 对于您给出
A = [1,51,3,1,100,199,3], maxSum = 51 + 1 + 199 = 251.
显然max(oddinexsum,evenIndexSum)
不起作用
我面临的主要问题是,我无法为元素提出选择标准。
给定一个选择准则,拒绝准则是微不足道的
标准的最大子序列算法在这里似乎不适用。
我尝试过一种动态规划方法,但也没有想到。
我唯一能想到的方法就是使用遗传算法
你将如何处理这个问题
max(oddIndexSum、evenIndexSum)不起作用
对于您给出的示例,它确实是这样的-但是,如果您有如下内容:A=[1,51,3,2,41,23,20]
,您可以有51+2+23=76
,也可以有
51+41+20=112
,明显更大,并且避免了相邻元素。这就是你要找的吗?当你用了一大堆花哨的词时,这基本上不是一个普通的旅行推销员的老问题吗
除了在这种情况下,您正在寻找通过(密集)图的最昂贵的路线?在这种情况下,顶点只是数字本身,边没有方向,没有权重,所有顶点都是连接的,除了原始列表中与它们相邻的顶点之外?如果保持两种状态,可以一步一步地构建最大子序列:
while you still have elements
find the largest element, add it to the sum
remove the element before and after the current
def maxsubseq(seq):
# maximal sequence including the previous item
incl = []
# maximal sequence not including the previous item
excl = []
for i in seq:
# current max excluding i
if sum(incl) > sum(excl):
excl_new = incl
else:
excl_new = excl
# current max including i
incl = excl + [i]
excl = excl_new
if sum(incl) > sum(excl):
return incl
else:
return excl
print maxsubseq([1,4,6,3,5,7,32,2,34,34,5])
如果您还想在列表中包含负面元素,则必须添加一些If
同样——用较小的行
相同--消除sum()
好吧,让我们优化它
总运行时间为O(n)的版本:
def maxsubseq4(iterable):
incl=[]#包括上一项的最大顺序
excl=[]#不包括上一项的最大序列
前缀=[]#两个序列的公共前缀
包括和,不包括和=0,0
对于iterable中的x:
如果包含和>=不包含和:
#不包括
不包括,不包括
不包括和,包括和=包括和,不包括和
其他:
#excl是两种车型的最佳起点
prefix.extend(excl)#O(n)在所有迭代中总计
excl=[]
包括=[]
包含和=不包含和
包括附加(x)
包括总和+=x
最佳=如果包含和>不包含和,则包含其他不包括
返回前缀+最佳#O(n)一次
克里斯的答案在列表[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值,如果您除了简单地获得正确答案外,还关心效率,那么还应该进行一些相同的优化(例如记忆化)
--马库斯克
[编辑]---
因为有些人似乎不明白这一点,我想解释一下我所说的回忆录是什么意思,以及为什么它很重要
您可以包装上面的函数,使其只计算每个数组的值一次(第一次调用时),并且在后续调用时只返回保存的结果。这将占用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)的单个循环,将其展开为伪基本:
最后,我们可以提取结果(按相反顺序):
请注意,我们刚刚手动完成的工作是一个优秀的现代语言编译器应该能够通过尾部递归、记忆等来完成的
我希望这足够清楚
--马库斯克
这是O(n)。奇怪的序言伪代码中的递归答案:
maxSum([]) = 0
maxSum([x]) = x
maxSum(A) = max(A[0] + maxSum(A[2..n]),
A[1] + maxSum(A[3..n]))
sum_excluded_last_item= 0
sum_included_last_item= 0
for each item in list
if (item>0)
last_sum_excluded_last_item= sum_excluded_last_item
sum_excluded_last_item= max(sum_included_last_item, sum_excluded_last_item + item)
sum_included_last_item= last_sum_excluded_last_item + item
else
sum_excluded_last_item= max(sum_excluded_last_item, sum_included_last_item)
sum_included_last_item= sum_excluded_last_item
max_sum= max(sum_excluded_last_item, sum_included_last_item)
适当处理超出范围的索引
编辑:这将简化为MarcusQ更好的答案:
maxSum([]) = 0
maxSum(A) = max(A[0] + maxSum(A[2..n]), maxSum(A[1..n]))
编辑:这里有一个版本,它返回实际的子序列,而不仅仅是其总和。它扩展了我的临时伪Prolog-C嵌合体的限制,所以我现在停止
maxSub([]) = []
maxSub(A) = sub1 = [A[0]] + maxSub(A[2..n])
sub2 = maxSub(A[1..n])
return sum(sub1) > sum(sub2) ? sub1 : sub2
为了避免递归,我们可以从反向而不是正向 ie)对于阵列A[1..n]>
maxSum(A,n): for all n
if n=0, maxSum = 0 else
if n=1, maxSum=A[1] else
maxSum = max(A[n] + maxSum(A,n-2), maxSum(A,n-1))
为了避免计算Max(A,n-2),在扩展maxSum(A,n-1)时,可以存储和计算它。这就是我要求逆转的原因。即maxSum(A,n-1)=max(A[n-1]+maxSum(A,n-3),maxSum(A,n-2)),其中in max(A,n-2)已经得到,无需重新计算)换句话说,使用上述公式计算从1到n的所有n的maxSum(A,n),以避免重新计算
e)n=2,maxSum=max(A[1]+maxSum(A,0),maxSum(A,1))
例如,n=3,maxSum=max(A[2]+maxSum(A,2),maxSum(A,2))等等。。到达最后的n。
这将是o(n)。作为Python oneliner(在注释中建议修改为@recursive):
例如:
>>> f([1,51,3,1,100,199,3])
[51, 1, 199]
它效率低下,但可以用来测试更快的解决方案
相同--在Emacs Lisp中
我们可以使用一个辅助数组B[0..n-1],其中B[i]是元素A[0..i]和C[0..n-1]的最大和,其中C[i]是布尔值,告诉我们A[i]是否在最大和子序列中:
B[0]=max(A[0],0); C[0]=(A[0]>0)
B[1]=max(B[0],A[1]); C[1]=(A[1]>B[0])
for i in [2..n-1]
if A[i]+B[i-2] > B[i-1]
C[i]=True
B[i]=A[i]+B[i-2]
else
C[i]=False
B[i]=B[i-1]
mssq=[]
i=n-1
while i>=0
if C[i]
push(A[i],mssq)
i=i-2
else
i=i-1
return mssq
这显然在O(n)时间和空间中起作用。事实上,这与MarcusQ的解决方案相同,只是进行了反向和优化。编辑:这确实是一个复制品,但我在发布后才意识到这一点 您可以在恒定的空间和线性时间内完成这项工作,前提是您不需要跟踪哪些项目有助于
maxSub([]) = []
maxSub(A) = sub1 = [A[0]] + maxSub(A[2..n])
sub2 = maxSub(A[1..n])
return sum(sub1) > sum(sub2) ? sub1 : sub2
maxSum(A,n): for all n
if n=0, maxSum = 0 else
if n=1, maxSum=A[1] else
maxSum = max(A[n] + maxSum(A,n-2), maxSum(A,n-1))
f = lambda L: L and max([L[0]] + f(L[2:]), f(L[1:]), key=sum)
>>> f([1,51,3,1,100,199,3])
[51, 1, 199]
(defun maxsubseq (L)
"Based on MarkusQ's and sth's answers."
(if (not L) L
(let ((incl (cons (car L) (maxsubseq (cddr L))))
(excl (maxsubseq (cdr L))))
(if (> (sum incl) (sum excl)) incl excl))))
(defun sum (L) (apply '+ L))
(defun maxsubseq-iter-impl (L excl incl)
(let ((next (if (> (car excl) (car incl)) excl incl)) (x (car L)))
(if (not L) (cdr next)
(maxsubseq-iter-impl (cdr L) next
(cons (+ x (car excl)) (cons x (cdr excl)))))))
(defun maxsubseq-iter (L) (reverse (maxsubseq-iter-impl L '(0) '(0))))
(require 'cl)
(loop for f in '(maxsubseq maxsubseq-iter)
collect (loop for L in '((1 51 3 1 100 199 3) (9 10 9))
collect (f L)))
(((51 1 199) (9 9)) ((51 1 199) (9 9)))
B[0]=max(A[0],0); C[0]=(A[0]>0)
B[1]=max(B[0],A[1]); C[1]=(A[1]>B[0])
for i in [2..n-1]
if A[i]+B[i-2] > B[i-1]
C[i]=True
B[i]=A[i]+B[i-2]
else
C[i]=False
B[i]=B[i-1]
mssq=[]
i=n-1
while i>=0
if C[i]
push(A[i],mssq)
i=i-2
else
i=i-1
return mssq
sum_excluded_last_item= 0
sum_included_last_item= 0
for each item in list
if (item>0)
last_sum_excluded_last_item= sum_excluded_last_item
sum_excluded_last_item= max(sum_included_last_item, sum_excluded_last_item + item)
sum_included_last_item= last_sum_excluded_last_item + item
else
sum_excluded_last_item= max(sum_excluded_last_item, sum_included_last_item)
sum_included_last_item= sum_excluded_last_item
max_sum= max(sum_excluded_last_item, sum_included_last_item)
int maxSeqSum(int *arr, int size) {
int i, a, b, c;
b = arr[0];
a = (arr[1] > arr[0]) ? arr[1]: arr[0];
for(i=2;i<size;i++) {
c = (a > (b + arr[i]))? a : (b + arr[i]);
b = a;
a = c;
}
return a;
}
find_max(int t, int n)
{
if(t>=n)
return 0;
int sum =0, max_sum =0;
for(int i=t; i<n; ++i)
{
sum = sum + A[i];
for(int j=i+2; j<n; ++j)
sum = sum + find_max(A[j], n);
if(sum > max_sum)
max_sum = sum;
}
return max_sum;
}