题目
类型:动态规划
解题思路
https://labuladong.github.io/algo/3/23/67/
https://leetcode.cn/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-er-fen-cha-zhao-tan-xin-suan-fa-p/
代码
动态规划
class Solution {public int lengthOfLIS(int[] nums) {// 定义:dp[i] 表示以 nums[i] 这个数结尾的最长递增子序列的长度int[] dp = new int[nums.length];// base case:dp 数组全都初始化为 1Arrays.fill(dp, 1);for (int i = 0; i < nums.length; i++) {for (int j = 0; j < i; j++) {if (nums[i] > nums[j])dp[i] = Math.max(dp[i], dp[j] + 1);}}int res = 0;for (int i = 0; i < dp.length; i++) {res = Math.max(res, dp[i]);}return res;}}
二分
class Solution {public int lengthOfLIS(int[] nums) {int len = nums.length;if (len <= 1) {return len;}// tail 数组的定义:长度为 i + 1 的上升子序列的末尾最小是几int[] tail = new int[len];// 遍历第 1 个数,直接放在有序数组 tail 的开头tail[0] = nums[0];// end 表示有序数组 tail 的最后一个已经赋值元素的索引int end = 0;for (int i = 1; i < len; i++) {int left = 0;// 这里,因为当前遍历的数,有可能比有序数组 tail 数组实际有效的末尾的那个元素还大// 【逻辑 1】因此 end + 1 应该落在候选区间里int right = end + 1;while (left < right) {// 选左中位数不是偶然,而是有原因的,原因请见 LeetCode 第 35 题题解// int mid = left + (right - left) / 2;int mid = (left + right) >>> 1;if (tail[mid] < nums[i]) {// 中位数肯定不是要找的数,把它写在分支的前面left = mid + 1;} else {right = mid;}}// 因为 【逻辑 1】,因此一定能找到第 1 个大于等于 nums[i] 的元素// 因此,无需再单独判断,直接更新即可tail[left] = nums[i];// 但是 end 的值,需要更新,当前仅当更新位置在当前 end 的下一位if (left == end + 1) {end++;}}// 此时 end 是有序数组 tail 最后一个元素的索引// 题目要求返回的是长度,因此 +1 后返回end++;return end;}}
