300_最长递增子序列

最长递增子序列

连接:https://leetcode.com/problems/longest-increasing-subsequence/description/

问题描述

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].

给定一个数组,找到其中的最长递增子序列,返回对应的长度

给定数组:[0,1,0,3,2,3]
最长递增子序列的长度为[0,1,2,3] 注意非连续

子序列和子串

注意子序列和子串的差距。

  • 子序列: 从数组中按照索引位置从小到大选择相应位置上的数值构成的序列,非连续
  • 子串: 从数组中截取的一段

https://blog.csdn.net/Mr_health/article/details/107348372

基本思想

解法1:

  • 问题类型:动态规划问题
  • 定义dp[i]: 以nums[i]为结尾的最长递增子序列的长度
  • 则dp[i] 依赖于 dp[0-i-1],即 dp[i] 依赖于 dp[0]~dp[i-1]的状态, 状态更新规则如下:
    • 0-i-1中, 使用指针j遍历 0-i-1,
      • 如果nums[i] > nums[j], 那么 t = max(L[j]+1,t)
  • 遍历结束 L[i] = t

时间复杂度\(O(n^2)\)

C++

    int lengthOfLIS(vector<int>& nums) {
        if (nums.size()<=0) return 0;
        if (nums.size()<=1) return 1;
        int size = nums.size();
        vector<int> dp(size,1); // dp[i] 以nums[i]为结尾的最长递增子序列
        int maxLength = 1; 
        for(int i=1;i<size;++i) {
            for (int j=0; j<i;++j) {
                if (nums[j] < nums[i]) {
                    dp[i] = max(dp[j]+1, dp[i]);
                }
            }
            maxLength = max(dp[i], maxLength);
        }
        return maxLength;
    }

python

   def lengthOfLIS(self, nums: List[int]) -> int:
        if len(nums) == 0: return 0
        if len(nums) == 1: return 1
        size = len(nums)
        dp = [1 for i in range(size)]  # 可以优化为 dp = [1] * size
        maxLength = 1
        i = 1
        while i < size:   # 可以优化为 for i in range(1, size):
            j = 0
            while j < i:  # 可以优化为 for j in range(i)
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i], dp[j]+1)
                elif nums[j] == nums[i]:
                    dp[i] = dp[j]
                j = j + 1
            maxLength = max(maxLength, dp[i])
            i = i + 1
        return maxLength

优化后代码如下:

展开查看

    def lengthOfLIS(self, nums: List[int]) -> int:
        if len(nums) == 0: return 0
        if len(nums) == 1: return 1
        size = len(nums)
        dp = [1 for i in range(size)]
        maxLength = 1
        for i in range(1,size):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i], dp[j]+1)
                elif nums[j] == nums[i]:
                    dp[i] = dp[j]
            maxLength = max(maxLength, dp[i])
        return maxLength

延申

  1. 借助二分搜索,可以将时间复杂度降低为\(O(nlogn)\)?
posted @ 2024-05-08 22:54  金字塔下的蜗牛  阅读(17)  评论(0)    收藏  举报