@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.最大子序和的更多相关文章

  1. LeetCode 53. 最大子序和(Maximum Subarray)

    53. 最大子序和 53. Maximum Subarray 题目描述 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. LeetCode53. M ...

  2. Java实现 LeetCode 53 最大子序和

    53. 最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 ...

  3. Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray)

    Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray) 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. ...

  4. leetcode 120. 三角形最小路径和 及 53. 最大子序和

    三角形最小路径和 问题描述 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] ...

  5. 1. 线性DP 53. 最大子序和.

    53. 最大子序和. https://leetcode-cn.com/problems/maximum-subarray/ func maxSubArray(nums []int) int { dp ...

  6. 53. 最大子序和(剑指 Offer 42)

    53. 最大子序和(剑指 Offer 42) 知识点:数组:前缀和:哨兵:动态规划:贪心:分治: 题目描述 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值. 要求 ...

  7. 【LeetCode】53.最大子序和

    最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: ...

  8. Leetcode题目53.最大子序和(动态规划-简单)

    题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6解释: 连 ...

  9. leetcode之53.最大子序和

    题目详情 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: ...

随机推荐

  1. MapReduce全局变量之捉虫记

    全局变量 写MapReduce程序时候,有时候须要用到全局变量,经常使用的全局变量实现由三种方式: 通过作业的Configuration传递全局变量.作业初始化的时候.conf.set(),须要的时候 ...

  2. cmd 监控网络状况

    提示:如果提示curl不是内部命令,请自行百度 windows 安装curl @echo off color 1f title 正在监控 echo 正在监控http://ioscheck.duapp. ...

  3. ADB安装及使用

    环境安装: 下载.安装和配置ADB     https://jingyan.baidu.com/article/22fe7cedf67e353002617f25.html 安装驱动adbdriver  ...

  4. MongoDB可视化工具--Robo 3T 使用教程

    MongoDB可视化工具--Robo 3T 使用教程 1. 到官网下载Robo 3T,网址如: https://robomongo.org/download. 2. 下载安装成功后,打开后点击左上角的 ...

  5. AI 线性回归

    线性回归(Linear Regression),顾名思义,输出是输入的线性函数.因为通常会附加偏置(bias)参数,所以实际是仿射函数. 参考链接: http://cs229.stanford.edu ...

  6. Spring Boot 之属性读写详解

    SpringBoot 之属性读写详解 加载 property 顺序 随机属性 命令行属性 Application 属性文件 Profile 特定属性 属性中的占位符 YAML 属性 访问属性 多 pr ...

  7. CF101D Castle 树形DP、贪心

    题目传送门 题意:给出一个有$N$个点的树,你最开始在$1$号点,经过第$i$条边需要花费$w_i$的时间.每条边只能被经过$2$次.求出到达除$1$号点外所有点的最早时间的最小平均值.$N \leq ...

  8. BZOJ1816 CQOI2010 扑克牌 贪心

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1816 题意:有$N$堆牌,第$i$堆牌有$c_i$张牌,还有$M$张$joker$,每 ...

  9. BJOI2018简要题解

    BJOI2018简要题解 D1T1 二进制 题意 pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 \(3\) 的倍数.他想研究对于二进制,是否也有类似的性质. 于是他生 ...

  10. 【SDOI2017】数字表格

    题面 题解 这道题目还有一种比较有意思的解法. 定义一种运算\((\mathbf f\oplus\mathbf g)(x) = \prod\limits_{d\mid x}\mathbf f(d)^{ ...