python如何求数组连续最大和的示例代码


Posted in Python onFebruary 04, 2020

题目描述:

一个有 n 个元素的数组,这 n 个元素既可以是正数也可以是负数,数组中连续的一个或多个元素可以组成一个连续的子数组,一个数组可能有多个这种连续的子数组,求子数组的最大值。例如,对于数组 [1,-2,4,8,-4,7,-1,-5] 而言,其最大和的子数组为 [4,8,-4,7],最大值为 15。

方法:

  • 蛮力法
  • 重复利用已经计算的子数组和
  • 动态规划
  • 优化的动态规划

1.蛮力法

找出所有的子数组,然后求出子数组的和,在所有子数组的和中取最大值。

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/29 21:59
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def maxSubArrSum(arr):
  if arr == None or len(arr) <= 0:
    print('参数不合理!')
    return
  thisSum = 0
  maxSum = 0
  i = 0
  while i < len(arr):
    j = i
    while j < len(arr):# j 控制连续子数组包含的元素个数
      thisSum = 0
      k = i # k 表示连续子数组开始的下标
      while k < j:
        thisSum += arr[k]
        k += 1
      if thisSum > maxSum:
        maxSum = thisSum
      j += 1
    i += 1
  return maxSum


if __name__ == '__main__':
  arr = [1, -2, 4, 8, -4, 7, -1, -5]
  print('1 max sub array sum:', maxSubArrSum(arr))

结果:

python如何求数组连续最大和的示例代码

算法性能分析:
这种方法的时间复杂度为O(n3);

2.重复利用已经计算的子数组和

由于 sum[i,j] = sum[i,j-1] + arr[j],在计算 sum[i,j] 的时候可以使用前面已计算出的 sum[i,j-1] 而不需要重新计算,采用这种方法可以省去计算 sum[i,j-1] 的时间,从而提高效率。

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/30 10:53
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def maxSubArrSum(arr):
  if arr == None or len(arr) <= 0:
    print('参数不合理!')
    return
  maxSum = -2 ** 31
  i = 0
  while i < len(arr): # i: 0~7
    sums = 0
    j = i
    while j < len(arr): # j: 0~7
      sums += arr[j] # sums 重复利用
      if sums > maxSum: # 每加一次就判断一次
        maxSum = sums
      j += 1
    i += 1
  return maxSum


if __name__ == '__main__':
  arr = [1, -2, 4, 8, -4, 7, -1, -5]
  print('2 max sub array sum:', maxSubArrSum(arr))

结果:

python如何求数组连续最大和的示例代码

算法性能分析:
使用了双重循环,时间复杂度为O(n2);

3.动态规划

首先可以根据数组最后一个元素 arr[n-1] 与最大子数组的关系分为以下三种情况讨论:
(包含或不包含,包含的话肯定以最后一个元素结尾;不包含的话,或者最后一个元素单独构成最大子数组,或者转换为求 arr[1…n-2] 的最大子数组)
(1) 最大子数组包含 arr[n-1],即最大子数组以 arr[n-1] 结尾;
(2) arr[n-1] 单独构成最大子数组;
(3) 最大子数组不包含 arr[n-1],那么求 arr[1…n-1] 的最大子数组可以转换为求 arr[1…n-2] 的最大子数组。
所以有:

python如何求数组连续最大和的示例代码

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/30 11:19
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def maxSubArrSum(arr):
  if arr == None or len(arr) <= 0:
    print('参数不合理!')
    return
  n = len(arr)
  End = [None] * n # End[i] 表示包含 arr[i] 的最大子数组和
  All = [None] * n # All[i] 表示最大子数组和
  End[n - 1] = arr[n - 1]
  All[n - 1] = arr[n - 1]
  End[0] = All[0] = arr[0]
  i = 1
  while i < n:
    End[i] = max(End[i - 1] + arr[i], arr[i]) # i=1时若arr[0]<0,则从arr[1]重新开始
    All[i] = max(End[i], All[i - 1])
    i += 1
  return All[n - 1]


if __name__ == '__main__':
  arr = [1, -2, 4, 8, -4, 7, -1, -5]
  print('3 max sub array sum:', maxSubArrSum(arr))

结果:

python如何求数组连续最大和的示例代码

算法性能分析:
时间复杂度为O(n);
由于额外申请了两个数组,所以空间复杂度为O(n);

4.优化的动态规划

方法3中每次其实只用到了 End[i-1] 与 All[i-1] ,而不是整个数组中的值,所以可以定义两个变量来保存 End[i-1] 与 All[i-1] 的值,并且可以反复利用。

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/30 11:55
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def maxSubArrSum(arr):
  if arr == None or len(arr) <= 0:
    print('参数不合理!')
    return
  nAll = arr[0] # 最大子数组和
  nEnd = arr[0] # 包含最后一个元素的最大子数组和
  i = 1
  while i < len(arr):
    nEnd = max(nEnd + arr[i], arr[i])
    nAll = max(nEnd, nAll)
    i += 1
  return nAll


if __name__ == '__main__':
  arr = [1, -2, 4, 8, -4, 7, -1, -5]
  print('4 max sub array sum:', maxSubArrSum(arr))

结果:

python如何求数组连续最大和的示例代码

算法性能分析:
时间复杂度为O(n);
空间复杂度为O(1);

引申:

在知道了子数组的最大值后,如何确定最大子数组的和?

思路:

python如何求数组连续最大和的示例代码

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/30 12:01
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
class Test:
  def __init__(self):
    self.begin = 0 # 记录最大子数组起始位置
    self.end = 0 # 记录最大子数组结束位置

  def maxSubArrSum(self, arr):
    n = len(arr)
    maxSum = -2 ** 31 # 子数组最大值
    nSum = 0 # 包含子数组最后一位的最大值
    nStart = 0
    i = 0
    while i < n:
      if nSum < 0:
        nSum = arr[i]
        nStart = i
      else:
        nSum += arr[i]
      if nSum > maxSum:
        maxSum = nSum
        self.begin = nStart
        self.end = i
      i += 1
    return maxSum

  def getBegin(self):
    return self.begin

  def getEnd(self):
    return self.end


if __name__ == '__main__':
  arr = [1, -2, 4, 8, -4, 7, -1, -5]
  t = Test()
  print('连续最大和为:', t.maxSubArrSum(arr))
  print('begin at ', t.getBegin())
  print('end at ', t.getEnd())

结果:

python如何求数组连续最大和的示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现堆排序的方法详解
May 03 Python
Python导入模块时遇到的错误分析
Aug 30 Python
python email smtplib模块发送邮件代码实例
Apr 26 Python
对PyTorch torch.stack的实例讲解
Jul 30 Python
总结python中pass的作用
Feb 27 Python
opencv与numpy的图像基本操作
Mar 08 Python
Django中reverse反转并且传递参数的方法
Aug 06 Python
Python日期格式和字符串格式相互转换的方法
Feb 18 Python
浅谈Python中os模块及shutil模块的常规操作
Apr 03 Python
用python画城市轮播地图
May 28 Python
Python 阶乘详解
Oct 05 Python
Python+Selenium实现读取网易邮箱验证码
Mar 13 Python
tensorflow 实现自定义layer并添加到计算图中
Feb 04 #Python
TensorFlow实现自定义Op方式
Feb 04 #Python
tensorflow使用指定gpu的方法
Feb 04 #Python
TensorFlow梯度求解tf.gradients实例
Feb 04 #Python
基于TensorFlow中自定义梯度的2种方式
Feb 04 #Python
tensorflow 查看梯度方式
Feb 04 #Python
opencv python图像梯度实例详解
Feb 04 #Python
You might like
php实现爬取和分析知乎用户数据
2016/01/26 PHP
在Win2003(64位)中配置IIS6+PHP5.2.17+MySQL5.5的运行环境
2016/04/04 PHP
PHP开发中csrf攻击的简单演示和防范
2017/05/07 PHP
PHP date()格式MySQL中插入datetime方法
2019/01/29 PHP
thinkphp 5框架实现登陆,登出及session登陆状态检测功能示例
2019/10/10 PHP
Laravel基础-关于引入公共文件的两种方式
2019/10/18 PHP
JavaScript中的私有/静态属性介绍
2012/07/26 Javascript
js异步加载的三种解决方案
2013/03/04 Javascript
JavaScript判断密码强度(自写代码)
2013/09/06 Javascript
在Iframe中获取父窗口中表单的值(示例代码)
2013/11/22 Javascript
jQuery中parents()和parent()的区别分析
2014/10/28 Javascript
jquery实现可拖拽弹出层特效
2015/01/04 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
Javascript将数字转化成为货币格式字符串
2016/06/22 Javascript
javascript类型系统_正则表达式RegExp类型详解
2016/06/24 Javascript
jQuery实现选项卡功能(两种方法)
2017/03/08 Javascript
移动端网页开发调试神器Eruda的介绍与使用技巧
2017/10/30 Javascript
vue2.0 兄弟组件(平级)通讯的实现代码
2018/01/15 Javascript
Angular5给组件本身的标签添加样式class的方法
2018/04/07 Javascript
浅谈Webpack打包优化技巧
2018/06/12 Javascript
mac上配置Android环境变量的方法
2018/07/08 Javascript
小程序日历控件使用方法详解
2018/12/29 Javascript
js获取对象,数组所有属性键值(key)和对应值(value)的方法示例
2019/06/19 Javascript
Python抓取电影天堂电影信息的代码
2016/04/07 Python
python选取特定列 pandas iloc,loc,icol的使用详解(列切片及行切片)
2019/08/06 Python
Python 爬虫实现增加播客访问量的方法实现
2019/10/31 Python
根据tensor的名字获取变量的值方式
2020/01/04 Python
Python脚本如何在bilibili中查找弹幕发送者
2020/06/04 Python
Pycharm学生免费专业版安装教程的方法步骤
2020/09/24 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
用你熟悉的语言写一个连接ORACLE数据库的程序,能够完成修改和查询工作
2012/06/11 面试题
优秀纪检干部材料
2014/08/27 职场文书
忠诚教育心得体会
2014/09/03 职场文书
教师党员个人剖析材料
2014/09/29 职场文书
主题班会开场白
2015/06/01 职场文书
Mysql8.0递归查询的简单用法示例
2021/08/04 MySQL