动态编程找到每个索引j在给定序列中以Xj结束的所有递增子序列的数量

时间:2015-07-03 06:25:17

标签: algorithm recursion sequence dynamic-programming

给定一系列实数(X1,X2,...,Xn)。编写一个有效的算法,找到每个索引j的严格增加的子序列的数量,以Xj结尾。

(严格增加的子序列定义为:Xa1,Xa2,...,Xai,当a1

我的解决方案应该包含一个在O(n^2)中解决此问题的递推公式和正确性证明,我只能使用嵌套for循环来解决它,我不确定是否有'是一个O(n^2)递归解决方案。

List a[1…n] <- [1…1]
 For j= 1 to n
    For i= 1 to j-1
       If xi<xj then
          a[i]= a[j]+a[i]; 

2 个答案:

答案 0 :(得分:0)

当您执行a[i] = a[j] + a[i]时,实际上您每次执行a[i]++时都会执行此a[j]==1。如果这不是显而易见的,您应该手动跟踪代码的执行情况,看看它实际上在做什么。

你可能想要的东西:

for j in range(n):
    for i in range(j):
        if x[i] < x[j]:
            a[j] += a[i]

重现关系是: 结束于j的递增子序列的数量是在每个索引小于j时结束的递增子序列数的总和,加上仅包含j的序列为1。

<强>分析

这是一个O(n ^ 2)解决方案。证明:外循环的第一次迭代,我们在内循环中循环1次(内循环在每次迭代时执行恒定的计算量)。每次我们增加j时,我们增加内循环中的迭代次数。所以我们最终总共在内部循环中调用代码 1 + 2 + 3 + ... (n-1) + n次。让f(n) = 1 + 2 + 3 + ... n

回想一下big {O的definition:f(n)= O(n ^ 2)表示有正常数ck,这样0 ≤ f(n) ≤ cn^2适用于所有n ≥ kck的值必须为函数f固定,且不得依赖于n

显然0 ≤ f(n)所以我们只需要表明存在一些ckf(n) ≤ cn^2所有n ≥ k。我会选择c=1k=1。您可以为所有f(n) <= n^2验证n

虽然您没有问,但您在下方的评论表明您希望证明这是我们可以获得的 tightest 界限。所以我将证明f(n) = Ω(n^2)

f(n)=Ω(n^2)如果某个常数为c>0且所有n都足够f(n) ≥ cn^2

让我们选择c=4。然后我们有f(n) = 1 + 2 + 3 + ... n >= (n/2) + (n/2)+1 + (n/2)+2 + ... n,我们只是从1 + 2 + ... (n/2)-1中减去f(n)来获得这种不等式。

另外,(n/2) + (n/2)+1 + (n/2)+2 + ... n >= (n/2)*(n/2)因为我们可以接受所有n/2>= n/2个字词,并且每个字词的下限均为n/2

但是(n/2)*(n/2) = (n^2)/4,所以我们对所有n都有f(n) >= (1/4)n^2,所以我们已经显示f(n) = Ω(n^2)

答案 1 :(得分:0)

所以基本上你想要一个自上而下的方法? 怎么样?

&#13;
&#13;
#include<bits/stdc++.h>
using namespace std;

int dp[15] = {0};
int a[15] = {3,2,1,14,2,4,5,9,7,20,12,13,6,8,11};

int DP(int x){
	if(x == 0) return 1;
	if(dp[x]) return dp[x];
	int ret = 1;
	for(int i=0; i<x; i++) if(a[x] > a[i]) ret += DP(i);
	return dp[x] = ret;
}
int main(){
	printf("%d\n", DP(14));
	return 0;	
}
&#13;
&#13;
&#13;

递推公式是相同的,它不依赖于您如何实施解决方案(自上而下或自下而上)

这是:

enter image description here