最长上升(下降)子序列
这也是动态规划的一种经典题型,牛客网也收录了这个题(https://www.nowcoder.com/questionTerminal/585d46a1447b4064b749f08c2ab9ce66);
例1:
输入:A = [157,232,6] n=3
输出:2
分析:
从后向前,求出以第i个元素为第一个元素时,最长上升序列的长度len[i].
初始化len[n]=1;
状态转移方程:len[i]=max(len[j]+1) 满足:(1) i<n (2) j = (i+1),(i+2),…,n (3)A[j]>A[i]
例1分析:
A = [157,232,6]n=3
(1)初始化:
len[n]=len[3]=1;
num=1;记录目前最长上升子序列的长度。
当前状态
A = [157,232,6]
len=[0,0,1]
num=1
(2)
len[2] =max (len[2+1]+1)= max (len[3]+1)=1 (由于不满足A[3]>A[2],即不满足6>232)
当前状态
A = [157,232,6]
len=[0,1,1]
num=1
(3)
len[1] =max(len[1+1]+1,len[1+2]+1) = max(len[2]+1,len[3]+1) (由于不满足A[3]>A[1],即不满足6>157)=1+1=2;
当前状态
A = [157,232,6]
len=[2,1,1]
num=2
(4)最终得出长度为2
JAVA代码:
public static int findLongest(int[] A, int n) {
int[] len = new int[n+1];//记录以第i个元素为子序列的第一个元素时,最长递增子序列的长度。
//初始化
len[n] = 1;
int num = 0;
for(int i = n;i>0;i--)
{
len[i]=1;
for(int j = n;j>i;j--)
{
if((A[i-1]<A[j-1])&&(len[i]<=len[j]))//上升
//if((A[i-1]>A[j-1])&&(len[i]<=len[j]))//下降
{
len[i]=len[j]+1;
if(len[i]>num) num = len[i];
}
}
}
return num;
}
在学习中,发现有的题还会问:方案数是多少?
这个问题问的想打人啊。。。。。。
(先把方法记录下来,刷题的时候,如果遇到了第二问,就再回来补充)
解决方案:
(1)对len[]排序
(2)用t[i]记录以第i个元素为第一个元素时,最长上升序列的不同方案数(注意啊,注意,是不同,需要去除重复的)
(3)初始化,如果len[i]=1,则t[i]=1;
(4)关于去重:当序列中有相同的元素时,为避免重复计数,从后向前递推时,当后面的元素遇到前面的相同元素时,则不再向前推。
例:A=[2,4,1,4,5]中有最长子序列[2,4,5]和[2,4,5],但其实他们两个是同样的子序列。