【leetcode笔记】Python实现 300. Longest Increasing Subsequence

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37251044/article/details/89043891

问题描述

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?

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

示例:

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

说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。

你算法的时间复杂度应该为 O(n**2) 。

进阶:

你能将算法的时间复杂度降低到 O(n log n) 吗?

法1.动态规划

用Dp[i]来保存从0-i的数组的最长递增子序列的长度。

如上数组Dp[0]=1,Dp[1]=1,Dp[2]=1,Dp[3]=2,Dp[4]=2。。。

计算Dp[i]的值可以对Dp[i]之前数值进行遍历,如果nums[i]>nums[j],则Dp[i] = max(Dp[i],Dp[j]+1)。

复杂度为O(n*n)

代码

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if nums==[]:
            return 0
        N = len(nums)
        Dp = [1]*N
        for i in range(N-1):
            for j in range(0,i+1):
                if nums[i+1]>nums[j]:
                    Dp[i+1] = max(Dp[i+1],Dp[j]+1)
        return max(Dp)

法2.覆盖法+二分查找

复杂度:O(n log n)

这种方法的解题步骤是:

  • 将第1个数字加入解集;
  • 依次读取后面的数字,如果此数字比解集中最后一个数字大,则将此数字追加到解集后,否则,用这个数字替换解集中第一个比此数字大的数,解集是有序的,因此查找可以用二分法,复杂度O(log n);
  • 最后的答案是解集的长度(而解集中保存的并不一定是合法解)。

举个栗子,输入为[1,4,6,2,3,5]:

  • 解集初始化为[1];
  • 读到4,将其追加到解集中,解集变为[1,4];
  • 读到6,将其追加到解集中,解集变为[1,4,6];
  • 读到2,用其替换解集中的4,解集变为[1,2,6],注意此时解集不是一个合法解,因为2是在6后出现的,但是解集的长度始终标识着当前最长序列的长度;
  • 读到3,用其替换解集中的6,解集变为[1,2,3];
  • 读到5,将其追加到解集中,解集变为[1,2,3,5],得到答案为解集长度4。

代码

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n == 0:
            return 0
        rst = [nums[0]]
        for i in range(1, n):
            if nums[i] > rst[-1]:
                rst.append(nums[i])
            else:
                index = self.midSearch(rst, nums[i])
                rst[index] = nums[i]
        return len(rst)

    def midSearch(self, s, k):
        p = 0
        q = len(s) - 1
        while(p <= q):
            m = (p + q)/2
            if s[m] == k:
                return m
            if s[m] > k:
                q = m - 1
            else:
                p = m + 1
        return p

链接:https://www.jianshu.com/p/a3cd9df6d9d1

参考:https://blog.csdn.net/xiaoxiaoley/article/details/78770109

参考:https://www.jianshu.com/p/a3cd9df6d9d1

猜你喜欢

转载自blog.csdn.net/weixin_37251044/article/details/89043891