给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
本题一看上去与以前的 最大子序列和 差不多,但是其实有实质性的差别。
1.最大子序列和 中 要求的是严格子序列,而本题中并不要求选中的序列是连续的
2.上面的这个区别就导致了子序和可以只用考虑dp[i] 与 dp[i-1] 这两个的关系。而本题必须要考虑前面所有。
因此本题用到的时间复杂度为 n 的平方 。
具体的代码作用或者逻辑在下面代码注释中有写出
class Solution {
public int lengthOfLIS(int[] nums) {
//定义 dp[i] 表示在以第i个结尾的序列中 最长上升的子序列的长度 dp[i]= dp[i-1]+1 ? 1,2,3,9,4,5,6 dp[3] =4 ,但是 dp[4]计算的时候并不依据dp[3] 因为num[3]>nums[4]但是 nums[4]>nums[2].
//所以得出结论 不能只看前面的一个点 比如 dp[4] 不能只比较 num[4]与 num[3] 相反,你需要对前面的所有nums 以及 dp 遍历
//继续分析dp[4] 我们看dp[2] 与nums[2] 此时 num[4]>num[2] 所以 dp[4]值为 dp[2]+1=4
int len =nums.length;
int [] dp = new int [len];
//初始化
for(int i=0;i<len;i++){
dp[i]=1;
}
//用i代表当前要求的节点
for(int i=1;i<len;i++){
//用j代表i之前会被遍历检查的节点
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
// (1) dp[i]=dp[j]+1; 这样做没有考虑到dp[i]在当前j之前就被赋值的情况
// 应该将当前的dp[i]与 dp【j】+1 进行比较 取最大值
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
}
int res=0;
//遍历返回最大的dp值即可
for(int i=0;i<len;i++){
res=Math.max(res,dp[i]);
}
return res;
}
}
本文介绍了一个算法问题,即在无序整数数组中寻找最长上升子序列的长度。通过动态规划的方法,详细解析了如何计算最长子序列长度,并提供了具体示例。
1732

被折叠的 条评论
为什么被折叠?



