Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
Have you met this question in a real interview?
Yes
Example
For [5, 4, 1, 2, 3], the LIS is [1, 2, 3], return 3
For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4
Challenge
Time complexity O(n^2) or O(nlogn)
思路: O(N^2) Using dp to store the current length max LIS.
O(nLogn) 参考 使用dp[i] 来存储一个当前长度为i , 以dp[i] 为右端的最小的串。每次查找更新的时候用二分法。
O(n ^ 2)
public int longestIncreasingSubsequence(int[] nums) {
// write your code here
int len = nums.length;
if(len < 1)
return 0;
int max = 1;
int[] dp = new int[len];
for(int i = 0 ; i < len; i++){
dp[i] = 1;
}
for(int i = len - 1; i >= 0; i--){
for(int j = i + 1; j < len; j++){
if(nums[j] >= nums[i]){
dp[i] = Math.max(dp[i], dp[j] + 1);
max = Math.max(max, dp[i]);
}
}
}
return max;
}
O(N*LogN)
public int longestIncreasingSubsequence1(int[] nums){
int len = nums.length;
if(len < 1)
return 0;
int max = 1;
int[] dp = new int[len + 1];
dp[1] = nums[0];
for (int i = 1; i < len; ++i) {
if (dp[max] <= nums[i]) {
dp[++max] = nums[i];
} else {
int pos = find(i, max, nums, dp);
dp[pos] = nums[i];
}
}
return max;
}
private int find(int idx, int max, int[] num, int[] dp)
{
int l = 1;
int r = max - 1;
//二分找到更新的位置
while (l <= r) {
int mid = (l + r) >> 1;
if (num[idx] > dp[mid] && num[idx] <= dp[mid + 1]) {
return mid + 1;
} else if (num[idx] > dp[mid]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
//找不到,就更新d[1],这个一定是长度为1的最小的
//否则,就到不了这一步了
return 1;
}