Longest Increasing Subsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [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. 

Note:

  • 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?

nlogn

一种优化时间复杂度到O(nlgn)的解法,这里用到了二分查找法,所以才能加快运行时间哇。思路是,我们先建立一个数组ends,把首元素放进去,然后比较之后的元素,如果遍历到的新元素比ends数组中的首元素小的话,替换首元素为此新元素,如果遍历到的新元素比ends数组中的末尾元素还大的话,将此新元素添加到ends数组末尾(注意不覆盖原末尾元素)。如果遍历到的新元素比ends数组首元素大,比尾元素小时,此时用二分查找法找到第一个不小于此新元素的位置,覆盖掉位置的原来的数字,以此类推直至遍历完整个nums数组,此时ends数组的长度就是我们要求的LIS的长度,特别注意的是ends数组的值可能不是一个真实的LIS,比如若输入数组nums为{4, 2, 4, 5, 3, 7},那么算完后的ends数组为{2, 3, 5, 7},可以发现它不是一个原数组的LIS,只是长度相等而已,千万要注意这点。参见代码如下:

二分查找:找到第一个比target大的,返回他的index,在这里 当nums[mid] <target 时,让start = mid,所以,最后nums[start]的位置不会比target大,最后返回end;

class Solution {
    public int lengthOfLIS(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        
        List<Integer> list = new ArrayList<>();
        
        list.add(nums[0]);
        for(int i = 1; i < nums.length;i++){
            if(list.get(0) >= nums[i]){
                list.set(0,nums[i]);
            }
            
            else if(list.get(list.size()-1) <= nums[i]){
                list.add(nums[i]);
            }
            
            else{
                list.set(binarySearch(list,nums[i]),nums[i]);
            }
        }
        
        return list.size();
    }
    
    public int binarySearch(List<Integer> list, int target){
        int start = 0, end = list.size() -1;
        
        while(start + 1 < end){
            int mid = start + (end - start) / 2;
            
            if(list.get(mid) >= target){
                end = mid;
            }else{
                start = mid;
            }
        }
        
        return end;
    }
}

Last updated