Leetcode——53.最大子序和
@author: ZZQ
@software: PyCharm
@file: leetcode53_最大子序和.py
@time: 2018/11/26 12:39
要求:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
方法如下:
方法一:暴力遍历法——O(n2)
class Solution():
  def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_len = len(nums)
        if nums_len == 0:
            return 0
        if nums_len == 1:
            return nums[0]
        max_value = nums[0]
        for i in range(nums_len):
            temp_max = 0
            for j in range(i, nums_len):
                temp_max += nums[j]  # 大量的重复运算,拖慢速度
                max_value = max(max_value, temp_max)
        return max_value
方法二:基于方法一避免大量的重复运算 ——O(n2)
class Solution():
  def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_len = len(nums)
        temp_sum = [0]*(nums_len+1)
        if nums_len == 0:
            return 0
        if nums_len == 1:
            return nums[0]
        max_value = nums[0]
        for i in range(nums_len):   # 基于方法一,避免大量的重复运算
            temp_sum[i] = temp_sum[i-1] + nums[i]
        for i in range(nums_len):
            for j in range(i, nums_len):
                temp_max = temp_sum[j] - temp_sum[i-1]
                max_value = max(max_value, temp_max)
        return max_value
方法三:分治法——O(nlogn)
        将求长度为n的序列中的最大子序和华为分求两个长度为n/2的序列的最大子序和
        将当前需要计算最大子串的序列分为两半,
        前半段从后往前遍历求最大子串lmax,
        后半段从前往后遍历求最大子串rmax,
        lmax+rmax就是当前长度为n的序列的最大子串,
        然后递归去找长度为n/2的序列的最大子串和,不断求小的序列的子串和。
        最后进行比较,得出最大值就是所求结果。
class Solution():
  def maxSubArray3(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_len = len(nums)
        if nums_len == 0:
            return 0
        left = 0
        right = nums_len - 1
        ans = self.maxSubArrayCompute(nums, left, right)
        return ans
    def maxSubArrayCompute(self, nums, left, right):
        """
        :type nums: List[int]
        :type left: int
        :type right: int
        :rtype: int
        """
        if left > right:
            return 0
        if left == right:
            return nums[left]
        middle = (left + right)/2
        left_max = self.maxSubArrayCompute(nums, left, middle)
        right_max = self.maxSubArrayCompute(nums, middle+1, right)
        lmax = nums[middle]
        left_sum = nums[middle]
        # 保证求得到子序列是连续的(也就是lmax + rmax是一个连续子序列的和)
        for i in range(middle-1, left-1, -1):  # 前半段逆序加(range(left,right,-1)表示逆序遍历)
            left_sum += nums[i]
            lmax = max(lmax, left_sum)
        rmax = nums[middle+1]
        right_sum = nums[middle+1]
        for i in range(middle+2, right+1):  # 后半段顺序加
            right_sum += nums[i]
            rmax = max(rmax, right_sum)
        return max(rmax+lmax, max(left_max, right_max))
方法四:扫描法——O(n)
        当我们加上一个正数时,和会增加;
        当我们加上一个负数时,和会减少。
        如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。
class Solution():
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_len = len(nums)
        current = nums[0]
        nums_sum = nums[0]
        # 我们考虑如果全是负数,那么返回最大的负数,如果最后的和为正,那么就使用扫描法
        for i in range(1, nums_len):
            if current < 0:
                current = nums[i]  # 当前数小于0 肯定会舍去(否则将会影响接下来的和),换为下一个数
            else:
                current += nums[i]  # 如果当前数不小于0,那么他会对接下来的和有积极影响
            if current > nums_sum:
                nums_sum = current  # 这里既实现了负数返回最大也实现了扫描法
            #这里其实已经隐式的列举了所有可能,保留了所有可能的最大值
        return nums_sum
方法五:动态规划——O(n)
        假设sum[i]为以i结尾的连续子串的和. 假设对于元素i,所有以它前面的元素结尾的子串和都已经求得,
        那么以第i个元素结尾且和最大的连续子串实际上,
           1)要么是以第i-1个元素结尾且和最大的连续子数组加上这个元素,
           2)要么只是第i个元素,即sum[i]
        所以当前的最大连续子串和的计算方法是max(sum[i-1]+nums[i], nums[i])
        这就是需要我们判断sum[i-1]是否大于0。
        由于每次运算只需要前一次的结果,因此算法的时间和空间复杂度都很小。
class Solution():
    def maxSubArray5(self, nums):  # 动态规划
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_len = len(nums)
        if nums_len == 0:
            return 0
        if nums_len == 1:
            return nums[0]
        nums_sum = nums[0]
        pre = nums[0]
        for i in range(1, nums_len):
            if pre > 0:
                pre += nums[i]
            else:
                pre = nums[i]
            nums_sum = max(nums_sum, pre)
        return nums_sum
Leetcode——53.最大子序和的更多相关文章
- LeetCode 53. 最大子序和(Maximum Subarray)
		53. 最大子序和 53. Maximum Subarray 题目描述 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. LeetCode53. M ... 
- Java实现 LeetCode 53 最大子序和
		53. 最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 ... 
- Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray)
		Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray) 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. ... 
- leetcode 120. 三角形最小路径和 及 53. 最大子序和
		三角形最小路径和 问题描述 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] ... 
- 1. 线性DP  53. 最大子序和.
		53. 最大子序和. https://leetcode-cn.com/problems/maximum-subarray/ func maxSubArray(nums []int) int { dp ... 
- 53. 最大子序和(剑指 Offer 42)
		53. 最大子序和(剑指 Offer 42) 知识点:数组:前缀和:哨兵:动态规划:贪心:分治: 题目描述 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值. 要求 ... 
- 【LeetCode】53.最大子序和
		最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: ... 
- Leetcode题目53.最大子序和(动态规划-简单)
		题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6解释: 连 ... 
- leetcode之53.最大子序和
		题目详情 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: ... 
随机推荐
- 【记录】GIT 常用命令记录
			1. 查看所有的提交版本,包含当你co到之前提交版本后依旧可以看到以前的日志 git log --graph --pretty=format:'%h -%d %s (%cr)' --abbrev-co ... 
- kafka的Java客户端示例代码(kafka_2.12-0.10.2.1)
			使用0.9开始增加的KafkaProducer和KafkaConsumer. Pom.xml <project xmlns="http://maven.apache.org/POM/4 ... 
- API--ResponseBody-类
			import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInc ... 
- linux 的常用命令---------第十一阶段
			软件管理rpm.yum 在 windows 与 linux 之间 实现小文件传输(仅支持在 X shell 中完成文件传输,虚拟机中不可实现): # yum install lrzsz -y ... 
- 转载  AutoFac常见用法总结
			第二节:框架前期准备篇之AutoFac常见用法总结 一. 说在前面的话 凡是大约工作在两年以上的朋友们,或多或少都会接触到一些框架搭建方面的知识,只要一谈到框架搭建这个问题或者最佳用法这个问题,势 ... 
- Appium——处理混合APP中H5的操作
			https://blog.csdn.net/iiyting/article/details/51887488 
- 用脚本将excel,csv等文件导入数据库
			文章转自 http://blog.csdn.net/lky5387/article/details/6043009 1.--导excel文件 select 订单编码 from OpenRowSet( ... 
- 【Codeforces 17E】Palisection
			Codeforces 17 E 题意:给一个串,求其中回文子串交叉的对数. 思路1:用哈希解决.首先求出每个点左右最长的回文串(要分奇数长度和偶数长度),然后记录经过每个点的回文串的个数,以及它们是在 ... 
- npm安装cnpm报错
			1.持久使用 npm config set registry https://registry.npm.taobao.org // 配置后可通过下面方式来验证是否成功npm config get re ... 
- HSF源码阅读
			HSF各组成之间的关系 1 服务提供者注册与发布 <bean id="hsfTestService" class="com.test.service.impl.Hs ... 
