Leetcode-最大子序和(53)

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

示例:输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6

思路:一开始除了暴力破解以外没有想到什么其他的方法,通过官方题解学习到了三种方法,分别为:贪心算法、分治法和DP动态规划法。

(1)贪心算法。总体思路为,每一步都选择局部最优解,则到达最后一步时所获得的也是整体最优解。具体来说就是遍历整个数组,在每个位置找到当前位置的最大和cur_max,然后更新整体最大和final_max.

1 class Solution:
2     def maxSubArray(self, nums: List[int]) -> int:
3         cur_max,final_max = nums[0],nums[0]
4         for word in nums[1:]:
5             cur_max = max(word,word+cur_max)
6             if cur_max > final_max:
7                 final_max = cur_max
8         return final_max

时间复杂度:O(n)  空间复杂度:O(1)

2)分治法。分治法的主要思想为,将原问题划分为若干个子问题,递归地解决子问题,合并子问题的解以得到原始问题的最终解。

在本题中,以数组nums最中间的字符为界,具有最大和的连续子数组可以分为三种情况:

  1. 递归找到左半部分具有最大和的子序列
  2. 递归找到右半部分具有最大和的子序列
  3. 从中间开始扫描,找到跨越中界线的具有最大和的子序列。
  4. 三者中最大的即为最终找到的具有最大和的子序列

   6>4>3,故最终结果为3

 

 

 1 class Solution:
 2     def maxSubArray(self, nums: List[int]) -> int:
 3         n = len(nums)
 4         if n == 1:
 5             return nums[0]
 6         else:
 7             left_max = self.maxSubArray(nums[:len(nums)//2])  #递归左半部分
 8             right_max = self.maxSubArray(nums[len(nums)//2:])  #递归右半部分
 9         #从中界线开始向左扫描 
10         l_max =  nums[len(nums)//2-1]
11         l_tmp = 0
12         for i in range(len(nums)//2-1,-1,-1):   
13             tmp_l += nums[i]
14             max_l = max(tmp_l,max_l)
15         max_r = nums[len(nums)//2]
16         #从中界线开始向右扫描 
17         tmp_r = 0
18         for i in range(len(nums)//2,len(nums)):
19             tmp_r += nums[i]
20             max_r = max(tmp_r,max_r)
21         return max(max_left,max_right,max_l+max_r)           

时间复杂度:O(nlogn)  空间复杂度:O(1)

(3)不太像动态规划法的动态规划法。用cur_sum表示当前最大连续子序列和,用ans表示最终结果。

遍历nums中的每一个数字number。若number>0,则该number对最后结果有增益效果(cur_sum加上一个正数一定大于当前的cur_sum),更新cur_sum+=number;若number<0,则该number对最后结果没有增益效果(因为该负数的存在一定会让最后的总和变小),因而舍弃该number,更新cur_sum = number。每遍历一个数字,更新ans=max(ans,cur_sum)。

 1 class Solution:
 2     def maxSubArray(self, nums: List[int]) -> int:
 3         ans = nums[0]
 4         cur_sum = 0
 5         for i in nums:
 6             if cur_sum >= 0 :
 7                 cur_sum += i
 8             else:
 9                 cur_sum = i
10             ans = max(ans,cur_sum)
11         return ans

时间复杂度:O(nlogn)  空间复杂度:O(1)

 

posted @ 2020-03-23 21:35  eltShawn  阅读(127)  评论(0编辑  收藏  举报