Day06 递增子序列问题
1、最长递增子序列
- 思路:
- 动态规划。一维dp数组表示 以num[i]为结尾的最长递增子序列长度
class Solution { public int lengthOfLIS(int[] nums) { int len = nums.length; //表示以num[i]为结尾的最长递增子序列长度 int[] dp = new int[len]; //最短递增子序列为1 dp[0] = 1; int ans = 1; for (int i = 1; i < len; i++) { int cur = nums[i]; //num[i]的前i-1个数中是否存在比num[i]小的数 dp[i] = 1; //查询比cur小的最长递增子序列的长度 for (int j = i - 1; j >= 0; j--) { if (cur > nums[j]) { dp[i] = Math.max(dp[j] + 1, dp[i]); } } //记录最大值 ans = Math.max(ans, dp[i]); } return ans; } } - 贪心+二分查找
- 要想最长上升,每次上升的数都尽可能小。维护每一个上升子序列的tail值数组tail
- 当存在一个数大于所有的tail时,应该新起一个上升子序列,即tail数组长度增加
- tail数组也是递增的(需要证明,抽象理解可以想蜘蛛纸牌)
class Solution { public int lengthOfLIS(int[] nums) { int len = nums.length; int[] tail = new int[len]; //最短递增子序列为1 tail[0] = nums[0]; int ans = 0; for (int i = 1; i < len; i++) { //如果nums[i]比当前递增数组的末尾集合的最大值大的话,最长子序列增加 if (nums[i] > tail[ans]) { tail[++ans] = nums[i]; } else { //寻找第一个比他小的tail值,并加到他后边 int l = 0, r = ans; while (l <= r) { int mid = (l + r) / 2; if (tail[mid] >= nums[i]){ r = mid - 1; }else { l = mid + 1; } } tail[l] = nums[i]; } } return ans + 1; } }
- 动态规划。一维dp数组表示 以num[i]为结尾的最长递增子序列长度
2、最长连续递增序列
- 思路:
- 动态规划
class Solution { public int findLengthOfLCIS(int[] nums) { int[] dp = new int[nums.length]; dp[0] = 1; int ans = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]){ dp[i] = dp[i - 1] + 1; }else { dp[i] = 1; } ans = Math.max(ans,dp[i]); } return ans; } }- 优化空间复杂度
class Solution { public int findLengthOfLCIS(int[] nums) { int ans = 1; int len = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]){ len ++; }else { len = 1; } ans = Math.max(ans,len); } return ans; } }