力扣上有一个经典的题目53. Maximum Subarry,题目描述如下。
Given an integer array nums, find the subarray with the largest sum, and return its sum.
思考如何取起点:假设我们当前取的subarray是 A r r a y [ i , j ] Array[i, j] Array[i,j](下标从i到j-1的数组)。如果将终点向后移动一位,得到 A r r a y [ i , j + 1 ] Array[i, j+1] Array[i,j+1],什么情况下会这个子数组是一定不考虑的答案呢?那就是当 A r r a y [ i , j ] < 0 Array[i, j]<0 Array[i,j]<0。因为 A r r a y [ i , j ] + n u m s [ j ] < n u m s [ j ] Array[i, j] + nums[j]
这也就是Kadane算法。维基百科中给出的代码是:
def max_subarray(numbers):
"""Find the largest sum of any contiguous subarray."""
best_sum = 0
current_sum = 0
for x in numbers:
current_sum = max(x, current_sum + x)
best_sum = max(best_sum, current_sum)
return best_sum
我们可能有一个疑问:为什么 A r r a y [ i , j ] < 0 Array[i, j] < 0 Array[i,j]<0那就把所有i到j-1都不作为起点的考虑呢?
给出简单证明:
假设 A r r a y [ i , j ] < 0 Array[i, j] < 0 Array[i,j]<0且有 A r r a y [ k , j ] > 0 , i < k < j Array[k, j] > 0, i
那么, A r r a y [ i , k ] < 0 Array[i, k]<0 Array[i,k]<0。
但是任何和小于0的subarray都不会和后面的subarray合并。
所以这个假设不成立。
class Solution {
public int maxSubArray(int[] nums) {
int maxSubarray = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
int currentSubarray = 0;
for (int j = i; j < nums.length; j++) {
currentSubarray += nums[j];
maxSubarray = Math.max(maxSubarray, currentSubarray);
}
}
return maxSubarray;
}
}
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_subarray = -math.inf
for i in range(len(nums)):
current_subarray = 0
for j in range(i, len(nums)):
current_subarray += nums[j]
max_subarray = max(max_subarray, current_subarray)
return max_subarray
Time Complexity: O ( N ) O(N) O(N)
Space Complexity: O ( 1 ) O(1) O(1)