zoukankan      html  css  js  c++  java
  • 最大子序和、最长上升子序列长度

    数据来源:https://leetcode-cn.com/problems/longest-increasing-subsequence/

    最大子序和

       给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

      代码如下所示:

     1 class Solution:
     2     def maxSubArray(self, nums: List[int]) -> int:
     3         length = len(nums)
     4         if length==1:
     5             return nums[0]
     6         max_ret = nums[0]
     7         cur_max = last_max = nums[0]
     8         for i in range(1, length):
     9             if last_max + nums[i] < nums[i]:
    10                 cur_max = nums[i]
    11             else:
    12                 cur_max = last_max + nums[i]
    13             if cur_max > max_ret:
    14                 max_ret = cur_max
    15             last_max = cur_max
    16         return max_ret

    最长上升子序列长度

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

      动态规划求解

        思路:利用动态规划的思想,我们可以将问题分解为到第i个元素的最长上升子序列长度的子问题。利用mem列表记录列表第一个元素到第 i 个元素的最长上升子序列长度,cur_mem变量记录了当前元素与 mem[j<i] 对应的子序列构成的 i-1 个子序列的最长上升子序列长度。代码如下所示:

     1 class Solution0:
     2     def lengthOfLIS(self, nums) -> int:
     3         if len(nums) == 0:
     4             return 0
     5         mem = [1 for _ in range(len(nums))]
     6         for i in range(1, len(nums)):
     7             cur_mem = []
     8             for j in range(i):
     9                 if nums[i] > nums[j]:
    10                     cur_mem.append(mem[j] + 1)
    11                 else:
    12                     cur_mem.append(1)                        
    13             mem[i] = max(cur_mem)
    14             print(mem)
    15         return max(mem)

        算法的时间复杂度为:O(n^2),空间复杂度O(n)。

        白话:我们求第 i 个元素对应的最长上升子序列时,是求包含nums[i] 这个元素的最长子序列长度;转移状态即为:当前元素加到mem[j],j<i 对应的子序列后,是否还是上升子序列,将是上升子序列的在对应的mem[j]上加1保存到cur_mem中,若不是,则保存1,最后将cur_mem中最大的元素保存为nums[i] ,最后输出mem中最大的元素即为最长上升子序列的长度。

      动态规划 + 二分查找

        在上面的解法中,变量列表nums是不可避免的;但是在循环里的每一步我们都需要计算 j 次(j<i),该循环的时间复杂度为O(n),这里的简化为使用二分法查找该长度,将时间复杂度将为O(log(n))。

        思路:引入一个与nums等长的全零列表tails;定义两个指针 i, j ;循环列表nums,在每次循环进行如下操作:

           1、i,j表示要查询的范围(索引),进行内层循环 while i<j;

           2、在内层循环中计算区间中:m = (i+j) // 2;

           3、计算tails[m]是否小于外层循环值num,若小于num,则令i = m+1;否则 j = m;

           4、内层循环结束时,将 tails[i] 赋值为 num。这里结合内层循环实现的功能是:外层循环的值若大于tails最后一个非零值则替换尾部的第一个零元素,若比它小,则替换前面序列中的一个数,这个数的前一个数比自己小(或不存在),后一个数比自己大(或不存在),注意,tails中的非零部分是严格上升序列,虽然顺序和原序列不一定一样,但是都可以映射为原序列中的一个子序列,也即最长子序列的长度一样。

     1 class Solution1:
     2     def lengthOfLIS(self, nums: [int]) -> int:
     3         tails, res = [0] * len(nums), 0
     4         for num in nums:
     5             i, j = 0, res
     6             while i < j:
     7                 m = (i + j) // 2
     8                 if tails[m] < num: i = m + 1 # 如果要求非严格递增,将此行 '<' 改为 '<=' 即可。
     9                 else: j = m
    10             tails[i] = num
    11             print(tails)
    12             if j == res: res += 1
    13         return res

        此算法引用:最长上升子序列(动态规划 + 二分查找,清晰图解)

  • 相关阅读:
    配置iis支持.json格式的文件
    This function has none of Deterministic,no sql,or reads sql data in its declaration and binary logging is enabled(you *might* want to use the less safe log_bin_trust_function_creators variable
    IIS Asp.Net 访问 Com组件 报拒绝访问
    记一次 mysql 启动没反应
    linux 下安装 redis
    Jexus 安装asp.net mvc EF 项目引发的错误总
    在CentOS中安装arial字体
    Navigator 对象
    location 对象属性
    history对象
  • 原文地址:https://www.cnblogs.com/dan-baishucaizi/p/11888808.html
Copyright © 2011-2022 走看看