题目:53.最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解题思路
设置两个变量,一个变量用来记录当前最大值,一个用来记录全局最大值
通过循环来遍历数组。以子数组的最后一个位置作为指针。
解法一:暴力算法
用两次for循环来遍历数组
时间复杂度O(n^2)
#C#
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0]; #全局最大
for (int i = 0; i < nums.length; i++) {
int temp = 0; #当前最大
for (int j = i; j < nums.length; j++) {
temp += nums[j];
if (temp > max) max = temp;
}
}
return max;
}
}
解法二:贪心算法
该算法通用且简单:遍历数组并在每个步骤中更新
对于初学者比较难理解的就是curr_sum
curr_sum并不是全局最大值,它比较出来的是截至到这个位置包括这个元素的子序和的最大值,是局部的。
#python
class Solution:
def maxSubArray(self, nums: 'List[int]') -> 'int':
n = len(nums)
curr_sum = max_sum = nums[0]
for i in range(1, n):
curr_sum = max(nums[i], curr_sum + nums[i])
max_sum = max(max_sum, curr_sum)
#curr_sum比较当前元素及包括当前元素位置的局部最大和
#max_sum记录全局最大子序和
return max_sum
时间复杂度:O(N)。只遍历一次数组。
空间复杂度:O(1),只使用了常数空间。
解法三:动态规划(DP)
DP法和贪心算法差不多,DP直接更改原本数组减少内存,相当于把
curr_sum直接储存在nums中,即nums[i]等价于curr_sum.
#python
class Solution:
def maxSubArray(self, nums: 'List[int]') -> 'int':
n = len(nums)
max_sum = nums[0]
for i in range(1, n):
if nums[i - 1] > 0:
nums[i] += nums[i - 1]
#沿数组移动并修改数组,令当前元素为局部最大值
max_sum = max(nums[i], max_sum)
return max_sum
时间复杂度:O(N)。只遍历一次数组。
空间复杂度:O(1),只使用了常数空间。
解法四:分治法
将一个数组对半分为左子数组和右子数组,则它的最大子序必然是以下情况中的一个:
- 全部在左子数组
- 全部在右子数组
- 穿过左右子数组
通过维护四个量:
以 左子数组的最左元素为左端点的最大子段和 【Lsum】
以 右子数组的最右元素为右端点的最大子段和 【Rsum】
以 左子数组的最右元素为右端点的最大子段和 【lsum】
以 右子数组的最左元素为左端点的最大子段和 【rsum】
其中【Lsum】、【Rsum】、【lsum+rsum】的最大值为原数组的最大子序和
用递归的方法,将原数组分成长度为1的子数组,使得每个元素都是某个子数组的最左元素/最右元素,然后回升的得到原数组的最大子序和。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
else:
max_left = self.maxSubArray(nums[0:len(nums) // 2])
max_right = self.maxSubArray(nums[len(nums) // 2:len(nums)])
#计算穿过中间的最大子序和
max_l = nums[len(nums) // 2 - 1] #左数组的最右元素
tmp = 0
for i in range(len(nums) // 2 - 1, -1, -1):
tmp += nums[i]
max_l = max(tmp, max_l) #左数组的包含最右元素的最大子序和
max_r = nums[len(nums) // 2]
tmp = 0
for i in range(len(nums) // 2, len(nums)):
tmp += nums[i]
max_r = max(tmp, max_r)
#返回三个中的最大值
return max(max_right,max_left,max_l+max_r)
198

被折叠的 条评论
为什么被折叠?



