• LeetCode 300——最长上升子序列


    1. 题目

    2. 解答

    2.1. 动态规划

    我们定义状态 state[i] 表示以 nums[i] 为结尾元素的最长上升子序列的长度,那么状态转移方程为:

    [state[i] = max(state[j] + 1) space 如果 space nums[i] > nums[j], 0 leqslant j < i ]

    class Solution {
    public:
    
        int lengthOfLIS(vector<int>& nums) {
    
            int n = nums.size();
            vector<int> state(n, 1);
    
            for (int i = 1; i < n; i++)
            {
                for (int j = i-1; j >= 0; j--)
                {
                    if (nums[i] > nums[j])
                        state[i] = max(state[i], state[j]+1);
                }
            }
    
            int ret = 0;
            for (int i = 0; i < n; i++)
                ret = max(ret, state[i]);
            return ret;
        }
    };
    

    易知上面代码的时间复杂度为 (O(n^2))

    2.2. 贪心思想

    我们用一个列表 result 来放置我们的最长上升子序列,然后向后遍历数组,如果 nums[i] > result[-1],说明当前元素应该被放进列表中去,因为这样就能组成一个更长的上升子序列;如果 nums[i] < result[-1],说明目前的上升子序列里面有大于当前元素的数据,贪心思想是说让我们用当前元素去替换掉上升子序列里面第一个大于等于当前元素的数,这样我们就可以有更大的操作空间去向 result 里面放更多的元素,从而形成更长的上升子序列

    比如 nums=[10,9,2,5,3,7,101,18],算法过程如下所示:

    [result = [10] \ result = [9] gets 9 < 10 \ result = [2] gets 2 < 9 \ result = [2, 5] gets 5 > 2 \ result = [2, 3] gets 3 < 5 \ result = [2, 3, 7] gets 7 > 3 \ result = [2, 3, 7, 101] gets 101 > 7 \ result = [2, 3, 7, 18] gets 18 < 101 \ ]

    class Solution:
        def binary_search(self, result, data):
            n = len(result)
            i, j = 0, n-1
            while i <= j:
                mid = i + (j - i) // 2
                if result[mid] >= data:
                    if mid == 0 or result[mid-1] < data:
                        return mid
                    else:
                        j = mid - 1
                else:
                    i = mid + 1
            return -1
    
    
        def lengthOfLIS(self, nums: List[int]) -> int:
    
            n = len(nums)
            if n == 0:  return 0
            result = [nums[0]]
            for i in range(1, n):
                if nums[i] > result[-1]:
                    result.append(nums[i])
                elif nums[i] < result[-1]:
                    #在result中找到第一个大于等于nums[i]的元素位置
                    pos = self.binary_search(result, nums[i])
                    result[pos] = nums[i]
    
            return len(result)
    

    循环需要 (n) 次,二分查找复杂度为 (O(logn)),所以总体代码的时间复杂度为 (O(nlogn))

    获取更多精彩,请关注「seniusen」!

  • 相关阅读:
    关于extern的用法
    建立CMenu菜单项,实现选中菜单项点击左键响应事件
    数据库常用语句
    圆周率的计算
    C++11中list特有版本的算法
    使用istream迭代器来输入输出数据
    C++中函数重载和函数覆盖的区别
    外置接口请求
    JSON转指定复杂对象
    FastDFS优化
  • 原文地址:https://www.cnblogs.com/seniusen/p/11991108.html
Copyright © 2020-2023  润新知