• LeetCode#53 Maximum Subarray


    Problem Difinition:

    Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

    For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
    the contiguous subarray [4,−1,2,1] has the largest sum = 6.

    More practice:

    If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

    Solution:

    1)动态规划.

    输入数组为nums,用 a[i] 表示nums[0...i]这部分元素的子序列(此子序列以元素nums[i]结尾,不管它以谁开头)能得到的最大累加和。则有递推关系:

    a[ i ] =nums[ i ]+ ( a[i-1] if a[i-1]>0 else 0)

    求解过程就是迭代整个数组,求最大的a[ i ]。可以用一个数组来保存所有的a[ i ],空间复杂度O(n)。

    然而实际上不需要一个数组来存放所有的a[ i ],而用一个变量代替。

     1     # @param {integer[]} nums
     2     # @return {integer}
     3     def maxSubArray(nums):
     4         
     5         maxSum=-sys.maxint
     6         sm=0
     7         begin=0
     8         end=0
     9         maxBegin=0
    10         maxEnd=0
    11         for i, n in enumerate(nums):
    12             sm+=n
    13             if sm>maxSum:
    14                 maxSum=sm
    15                 maxBegin=begin
    16                 maxEnd=end
    17             if sm<=0:
    18                 begin=i+1
    19                 end=i+1
    20                 sm=0
    21             else:
    22                 end+=1
    23         return nums[maxBegin: maxEnd+1]

    以上算法会求出得到最大和的完整子序列,更通用,思路也表达得比较清晰。然而题目的要求只是求出这个最大和,所以可以精简很多:

     1     # @param {integer[]} nums
     2     # @return {integer}
     3     def maxSubArray(nums):
     4         maxSum=-sys.maxint
     5         sm=0
     6         for n in nums:
     7             sm+=n
     8             maxSum=max(maxSum, sm)
     9             sm=max(sm, 0)
    10         return maxSum

    实际上想法很简单,逐一累加元素,一旦和不大于0,则从下一个位置开始,重新累加,并在这个过程中不断更新最大和。

    2)分治。

    基本思想:

      1._分。把数组切成左右两部分,那么给出最大累加和的子序列,要么全在左边,要么全在右边,要么就横跨左右两边(子序列包含了中间元素)

      2._合。整个数组的最大累加和就是max(左边的最大和, 右边的最大和, 跨越两边的最大和)

           于是可以:a.先分别求左右两个部分的最大累加和,这是一个递归的过程;

              b.求跨越左右两边的子序列能够给出的最大累加和;

              c.返回三个和中的最大值,作为整个序列的最大累加和。

        关键是b.过程。其实也很简单,以中间元素为起点,分别向左右两边扩展,求出在左边子序列中,后缀序列能达到的最大累加和;以及

        右边序列中,前缀序列能达到的最大累加和,这俩累加和加起来即可。

        设中间节点的下标为m,那所谓的左边子序列的后缀就是:nums[...m-2, m-1, m],右边子序列的前缀就是nums[m+1, m+2...].

        

     1     # @param {integer[]} nums
     2     # @return {integer}
     3     def maxSubArray(self, nums):
     4         if len(nums)==0:
     5             return 0
     6         return self.recur(nums, 0, len(nums)-1)
     7 
     8 
     9     def recur(self, nums, start, end):
    10         if start==end:  #one element
    11             return nums[start]
    12         mid=(start+end)/2
    13         leftAns=self.recur(nums, start, mid)
    14         rightAns=self.recur(nums, mid+1, end)
    15         leftMax=nums[mid]
    16         rightMax=nums[mid+1]
    17         tmp=0
    18         for i in range(mid, start-1, -1):  #直接加到最后吧
    19             tmp+=nums[i]
    20             leftMax=max(leftMax, tmp)
    21         tmp=0
    22         for i in range(mid+1, end+1):
    23             tmp+=nums[i]
    24             rightMax=max(rightMax, tmp)
    25         return max(leftAns, rightAns, leftMax+rightMax)


  • 相关阅读:
    .Net Core部署到CentOS
    Docker容器中开始.Net Core之路
    自我总结和学习表单提交的几种方式 (二)
    自我总结和学习表单提交的几种方式 (一)
    Asp.Net MVC下自定义错误页和展示错误页的几种方式
    .Net下发送邮件遇到问题及解决方案
    Asp.Net MVC CodeFirst模式数据库迁移步骤
    利用微软认知服务实现语音识别功能
    Asp.Net MVC路由生成URL过程
    针对于多线程概念的理解
  • 原文地址:https://www.cnblogs.com/acetseng/p/4703378.html
Copyright © 2020-2023  润新知