学习交流加
- 个人qq:
1126137994- 个人微信:
liu1126137994- 学习交流资源分享qq群:
962535112
这是一个经典的LIS(即最长上升子序列)问题,请设计一个尽量优的解法求出序列的最长上升子序列的长度。
给定一个序列arr及它的长度n(长度小于等于500),请返回LIS的长度。
测试样例:
[2,1,5,3,6,4,8,9,7],9
返回:5
分析思路:化简到子问题,那么这道题应该是化简到求该序列长度的前1,2,3,4,5,6…n个数的最长上升子序列问题
那么同样是开辟一个数组dp[n] 这里开辟的是数组还是矩阵,是根据实际情况而来。那么dp[i]就代表必须以arr[i]结尾的情况下,arr[0…i]的最长上升子序列的长度。
由上图的分析可知:
dp[0]=1;
dp[1] 取决于arr[1]是否大于arr[0] 本题是不大于,所以dp[1]=1;
dp[2]取决于arr[2]是否大于arr[j](j=0~1),大于arr[j]的话,那么就取dp[j]+1的最大值
dp[3]取决于arr[3]是否大于arr[j](j=0~2),大于arr[j]的话,那么就取dp[j]+1的最大值
dp[4]取决于arr[4]是否大于arr[j](j=0~3),大于arr[j]的话,那么就取dp[j]+1的最大值
那么dp[i]的表达式就应该是:
dp[i]=max{dp[j]+1(j=0~(i-1)),且arr[i]>arr[j]}
由以上分析,可写程序如下:
class LongestIncreasingSubsequence {
public:
int getLIS(vector<int> A, int n) {
// write code here
int dp[n];
/* 初始化dp */
for(int i=0;i<n;i++)
{
dp[i]=1;
}
int Max=1;
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(A[i]>A[j])
{
//注意dp[j]+1这个表达式只能放到判断语句里面,这样才不会改变它的值(只做判断),
//如果改变了dp[j]的值,将会影响下一次循环的计算
if((dp[j]+1)>dp[i])
dp[i]=dp[j]+1;
}
}
/* 外部每循环一次,则求得了dp[i]的值,选出每次循环后得到的最大值,就是最终需要返回的值 */
if(dp[i]>Max)
Max=dp[i];;
}
return Max;
}
};
动态规划的思想!!!化整体为0,1,2…先计算子问题,再合并计算整体问题!!!