publicintmaxSubArray(int[] nums){ int n = nums.length; int res = Integer.MIN_VALUE; // 穷举各种可能的子数组 nums[i..j] for (int i = 0; i for (int j = i; j // 计算子数组 nums[i..j] 的和 int sum = 0; for (int k = i; k <= j; k++) { sum += nums[k]; } res = Math.max(res, sum); } } return res; }
在上面的代码中,我们在第一层循环确定一个变量
i
,然后在第二层循环依次计算
nums[i..i]
、
nums[i..i+1]
一直到
nums[i..n-1]
的和。我们可以直接在一个
sum
变量上依次累加,而不需要使用第三层循环进行累加。
修改后的代码如下:
publicintmaxSubArray(int[] nums){ int n = nums.length; int res = Integer.MIN_VALUE; for (int i = 0; i int sum = 0; for (int j = i; j sum += nums[j]; res = Math.max(res, sum); } } return res; }
// 计算 nums[lo..hi] 的最大子数组和 // lo 表示 low,hi 表示 high privateintmaxSubArray(int[] nums, int lo, int hi){ if (hi return Integer.MIN_VALUE; } elseif (hi == lo) { return nums[lo]; }
int mid = lo + (hi - lo) / 2; // 计算左半部分数组的最大子数组和 int max_left = maxSubArray(nums, lo, mid); // 计算右半部分数组的最大子数组和 int max_right = maxSubArray(nums, mid+1, hi); // 计算穿过中间线的子数组的最大和 int max_mid = maxMidSubArray(nums, lo, mid, hi); return Math.max(max_left, Math.max(max_mid, max_right)); }
privateintmaxMidSubArray(int[] nums, int lo, int mid, int hi){ // 计算中间线左侧(且紧挨着中间线)的最大子数组和 int max_mid_left = 0; if (mid >= lo) { max_mid_left = nums[mid]; int sum = 0; for (int i = mid; i >= lo; i--) { sum += nums[i]; max_mid_left = Math.max(max_mid_left, sum); } }
// 计算中间线右侧(且紧挨着中间线)的最大子数组和 int max_mid_right = 0; if (mid + 1 <= hi) { max_mid_right = nums[mid+1]; int sum = 0; for (int i = mid + 1; i <= hi; i++) { sum += nums[i]; max_mid_right = Math.max(max_mid_right, sum); } }
publicintmaxSubArray(int[] nums){ int dp = 0; int res = Integer.MIN_VALUE; for (int k = 1; k <= nums.length; k++) { dp = Math.max(dp, 0) + nums[k-1]; res = Math.max(res, dp); } return res; }