0300. Longest Increasing Subsequence - kumaeki/LeetCode GitHub Wiki
0300. Longest Increasing Subsequence
Given an integer array nums, return the length of the longest strictly increasing subsequence.
A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].
Example 1:
Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Example 2:
Input: nums = [0,1,0,3,2,3]
Output: 4
Example 3:
Input: nums = [7,7,7,7,7,7,7]
Output: 1
Constraints:
- 1 <= nums.length <= 2500
- -10^4 <= nums[i] <= 10^4
解法1
定义一维数组dp, dp[i]表示到一定包括 i 的时候的递增数列的元素个数.
对于i, 如果j< i,并且 nums[j] < nums[i], 那么dp[i] 就取 dp[j] +1 和dp[i] 中的较大值.
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int n = nums.length, max = 1;
int[] dp = new int[n];
dp[0] = 1;
for(int i = 1; i < n; i++){
int res = 1;
int num = nums[i];
for(int j = i-1; j >= 0; j--){
if(num > nums[j])
res = Math.max(res, dp[j] + 1);
}
dp[i] = res;
max = Math.max(max, dp[i]);
}
return max;
}
}
定义辅助数组m,长度为n+1.
对于input来说,假设有长度为 j 的递增数列, 那么可能存在多个不同的数列,那么用m[ j ] 来保存着多个不同数列中,最小的最大值在nums中对应的下标.
定义主数组p,长度为n.
p[ k ]表示以nums[ k ] 为最大值的递增数列的前一个元素在nums中的下标.每次更新m[ j ] 的时候,将m[j - 1]存入p[ k ].
需要注意的是p的下标和nums的下标是一一对应的,所以在最后求LIS的时候,可以直接用 k = p[k] 来循环得到前一个数字.
定义变量l, 表示到目前为止递增数列的最大值
解法2
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int n = nums.length;
// m[j] 表示长度为j的递增数列中,最小的最大值在nums中的下标
int[] m = new int[n+1];
// 到目前位置的递增数列的最大值
int l = 0;
for(int i = 0; i < n; i++){
// 二叉搜索,在已知的递增数列的长度中找到当前nums[i]对应的位置
int lo = 1, hi = l,newl = 1;
while(lo <= hi){
int mid = (lo + hi) / 2;
if(nums[m[mid]] < nums[i]){
lo = mid + 1;
newl = lo;
}else
hi = mid - 1;
}
// 替换掉长度为newl的递增数列的最大值在nums中的下标
m[newl] = i;
if(newl > l)
l = newl;
}
return l;
}
}