Leetcode-300. 最长上升子序列

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:

  • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
  • 你算法的时间复杂度应该为 O(n2) 。
  • 进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

解法:1.DP法。这里给出的dp[i]的含义是从头到i(必须包含i)的最长子序列的长度,定义j是小于i的索引,范围在0-i,则状态转移方程就是当nums[i]>nums[j]时,dp[i] = max{ dp[j]+1 },选出所有自序列中最长的上升子序列,最终的最长子序列是所有dp[i]中最大的,而并非是dp[n-1]。时间复杂度在O(N^2)2. 二分法,首先构建一个数组res用来存储最长上升子序列,遍历整个nums,如果nums[i]在res中是最大的,则加到最后,如果不是,则替换掉比他大但是最接近他的数。这个思想就是不断的扩大其他数能进来的余地。时间复杂度,遍历nums为N,找到比他大的元素时间为logN,所以O(NlogN)

  • Java
class Solution {
   
    public int lengthOfLIS(int[] nums) {
   
        if (nums.length==0 || nums==null) return 0;
        int res = 1;
        int[] dp = new int[nums.length];
        for (int i=0;i<nums.length;i++) dp[i] = 1;
        for (int i=1;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);
            }
            res = dp[i]>res?dp[i]:res;
        }
        return res;
    }
}
  • Python
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums: return 0
        res = 1
        dp = [1 for _ in range(len(nums))]
        for i in range(1, len(nums)):
            for j in range(0,i):
                if nums[i]>nums[j]:
                    dp[i] = max(dp[i], dp[j]+1)
            res = max(res, dp[i])
        return res

  • Java
class Solution {
   
    public int lengthOfLIS(int[] nums) {
   
        int[] tails = new int[nums.length];
        int size = 0;
        for (int x : nums) {
   
            int i = 0, j = size;
            while (i != j) {
   
                int m = (i + j) / 2;
                if (tails[m] < x)
                    i = m + 1;
                else
                    j = m;
            }
            tails[i] = x;
            if (i == size) ++size;
        }
        return size;
}
}
  • Python
def lengthOfLIS(self, nums):
    tails = [0] * len(nums)
    size = 0
    for x in nums:
        i, j = 0, size
        while i != j:
            m = (i + j) / 2
            if tails[m] < x:
                i = m + 1
            else:
                j = m
        tails[i] = x
        size = max(i + 1, size)
    return size