给定一系列实数(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];
答案 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)表示有正常数c
和k
,这样0 ≤ f(n) ≤ cn^2
适用于所有n ≥ k
。 c
和k
的值必须为函数f固定,且不得依赖于n
。
显然0 ≤ f(n)
所以我们只需要表明存在一些c
和k
,f(n) ≤ cn^2
所有n ≥ k
。我会选择c=1
和k=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)
所以基本上你想要一个自上而下的方法? 怎么样?
#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;
递推公式是相同的,它不依赖于您如何实施解决方案(自上而下或自下而上)
这是: