问题:
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
解决:
【题意】求最长递增子序列(可以不连续)
① 使用动态规划。dp[i]表示以nums[i]为结尾的最长递增子串的长度。dp[i] = max(dp[i], dp[j] + 1),时间复杂度O(n^2)。
class Solution { //32ms
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp,1);
int max = 0;
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);
}
}
max = Math.max(max,dp[i]);
}
return max;
}
}
② 二分查找法,时间复杂度O(nlogn)。使用如下算法:
对于每个数字
如果(则为list.size()== 0)
加入列表
else if(num> list中的最后一个元素)
加入列表
其他
替换列表中最小但大于num的元素
class Solution { //3ms
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0){
return 0;
}
List<Integer> list = new ArrayList<>();
for (int n : nums){
if (list.size() == 0 || n > list.get(list.size() - 1)){
list.add(n);
}else{
int left = 0;
int right = list.size() - 1;
while(left < right){
int mid = (right - left) / 2 + left;
if (list.get(mid) < n){
left = mid + 1;
}else{
right = mid;
}
}
list.set(right,n);
}
}
return list.size();
}
}
③ 将二分搜索的方法提取出来。
class Solution { //0ms public int lengthOfLIS(int[] nums) { if(nums == null || nums.length == 0){ return 0; } int[] record = new int[nums.length + 1]; record[0] = nums[0]; int len = 1; for(int i = 1; i < nums.length; i++){ int crt = nums[i]; if(crt <= record[0]){ record[0] = crt; }else if(crt > record[len - 1]){ record[len] = crt; len ++; }else{ insertNum(record, len, crt); } } return len; } private void insertNum(int[] record, int len, int crt){ int start = 0, end = len - 1; while(start + 1 < end){ int mid = start + (end - start) / 2; if(record[mid] == crt){ return; }else if(record[mid] < crt){ start = mid; }else{ end = mid; } } if(record[start] >= crt){ record[start] = crt; }else{ record[end] = crt; } } }