本文为Python算法题集之一的代码示例
题目53:最大子数组和
说明:给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
提示:
-
1 <= nums.length <= 105
-
-104 <= nums[i] <= 104
- 问题分析
- 本题为求数组中的子数组的最大和
- 主要的计算为2个,1子数组遍历,2子数组求和
- 基本的遍历为双层循环,双层循环遍历子数组,每个子数组求和一次,所以基本的时间算法复杂度为(On2)
- 优化思路
-
减少循环层次
-
减少计算类别
-
通过动态规划分析最优路径
- 前缀和之差(第1到第n的累加为前缀和,前缀和之间的差为两个元素之间子数组的和)
- 递归思路,第n个元素为止的最大和,为之前的最大和max_n与包含元素n的子数组最大和【max(premax+元素n、元素n)】中最大者
CheckFuncPerf
是我写的函数用时和内存占用模块,地址在这里:Python算法题集_检测函数用时和内存占用的模块【自搓】- 测试的超时测试用例文件是官网的,已上传到CSDN,地址在这里:力扣算法题:最大子数组和测试用例,用于测试超时,数组长度21808(估计是2月1日过审)
-
标准求解,双层循环,超时失败
pythonimport CheckFuncPerf as cfp def maxSubArray_base(nums): if len(nums) == 1: return nums[0] imaxsum, ileftsum = nums[0], nums[0] for iIdx in range(len(nums)-1): ileftsum += nums[iIdx] irightsum = 0 for jIdx in range(iIdx+1, len(nums)): irightsum += nums[jIdx] if ileftsum > 0: if ileftsum+irightsum > imaxsum: imaxsum = ileftsum+irightsum else: if irightsum > imaxsum: imaxsum = irightsum return imaxsum testcase_big = open(r'testcase/hot13_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '') testcase_big = testcase_big.split(',') nums = [int(x) for x in testcase_big] result = cfp.getTimeMemoryStr(maxSubArray_base, nums) print(result['msg'], '执行结果 = {}'.format(result['result'])) # 运行结果 函数 maxSubArray_base 的运行时间为 19834.08 ms;内存使用量为 4.00 KB 执行结果 = 1364833
-
优化版一【采用前缀和】,虽有想法,超时依旧
pythonimport CheckFuncPerf as cfp def maxSubArray_ext1(nums): if len(nums) == 1: return nums[0] presum = [0] * len(nums) isum, imaxsum = 0, nums[0] for iIdx in range(len(nums)): isum += nums[iIdx] presum[iIdx] = isum for iIdx in range(len(nums)-1): for jIdx in range(iIdx+1, len(nums)): imaxsum = max(imaxsum, presum[iIdx], presum[jIdx], presum[jIdx]-presum[iIdx]) return imaxsum testcase_big = open(r'testcase/hot13_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '') testcase_big = testcase_big.split(',') nums = [int(x) for x in testcase_big] result = cfp.getTimeMemoryStr(maxSubArray_ext1, nums) print(result['msg'], '执行结果 = {}'.format(result['result'])) # 运行结果 函数 maxSubArray_ext1 的运行时间为 15518.62 ms;内存使用量为 144.00 KB 执行结果 = 1364833
-
优化版二【滑动窗口,单层循环】,勉强通过,超过27%
pythonimport CheckFuncPerf as cfp def maxSubArray_ext2(nums): if len(nums) == 1: return nums[0] presum = [0] * len(nums) isum, imaxsum, iminsum = 0, nums[0], nums[0] for iIdx in range(len(nums)): isum += nums[iIdx] presum[iIdx] = isum if iIdx > 0: imaxsum = max(imaxsum, isum, isum - iminsum) iminsum = min(isum, iminsum) return imaxsum testcase_big = open(r'testcase/hot13_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '') testcase_big = testcase_big.split(',') nums = [int(x) for x in testcase_big] result = cfp.getTimeMemoryStr(maxSubArray_ext2, nums) print(result['msg'], '执行结果 = {}'.format(result['result'])) # 运行结果 函数 maxSubArray_ext2 的运行时间为 6.99 ms;内存使用量为 296.00 KB 执行结果 = 1364833
-
优化版三【动态规划,递归思路求解】,马马虎虎,超过60%
pythonimport CheckFuncPerf as cfp def maxSubArray_ext3(nums): imaxpre, imaxsum = 0, nums[0] for iIdx in range(len(nums)): imaxpre = max(nums[iIdx], nums[iIdx] + imaxpre) imaxsum = max(imaxsum, imaxpre) return imaxsum testcase_big = open(r'testcase/hot13_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '') testcase_big = testcase_big.split(',') nums = [int(x) for x in testcase_big] result = cfp.getTimeMemoryStr(maxSubArray_ext3, nums) print(result['msg'], '执行结果 = {}'.format(result['result'])) # 运行结果 函数 maxSubArray_ext3 的运行时间为 5.99 ms;内存使用量为 4.00 KB 执行结果 = 1364833
-
优化版四【分支改良】,有所改善,超越83%
在优化版四的基础上,进行流程分支改良,去掉了一批加法计算
pythonimport CheckFuncPerf as cfp def maxSubArray_ext4(nums): imaxpre, imaxsum = 0, nums[0] for iIdx in range(len(nums)): if imaxpre > 0: imaxpre = nums[iIdx] + imaxpre else: imaxpre = nums[iIdx] imaxsum = max(imaxsum, imaxpre) return imaxsum testcase_big = open(r'testcase/hot13_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '') testcase_big = testcase_big.split(',') nums = [int(x) for x in testcase_big] result = cfp.getTimeMemoryStr(maxSubArray_ext4, nums) print(result['msg'], '执行结果 = {}'.format(result['result'])) # 运行结果 函数 maxSubArray_ext4 的运行时间为 4.02 ms;内存使用量为 0.00 KB 执行结果 = 1364833
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~