最大子数组和 | LeetCode-53 | 贪心算法 | 动态规划

贪心练习题


LeetCode链接:53. 最大子数组和

1.题目描述

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。

示例 1:

1
2
3
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

1
2
输入:nums = [1]
输出:1

示例 3:

1
2
输入:nums = [5,4,-1,7,8]
输出:23

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

2.题解

2.1 贪心算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int maxSubArray(int[] nums) {
// 贪心算法
int sum = 0; // 当前连续子数组的和
int result = Integer.MIN_VALUE; // 用于记录最大的子数组和,初始化为最小整数值

// 遍历数组
for (int i = 0; i < nums.length; i++) {
sum += nums[i]; // 将当前元素加入到当前子数组的和中
result = Math.max(result, sum); // 更新最大子数组和
sum = Math.max(sum, 0); // 如果当前子数组和为负数,则将其重置为 0,开始新的子数组
}
return result; // 返回最大子数组和
}
}

2.2 动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int maxSubArray(int[] nums) {
// 动态规划
int[] dp = new int[nums.length]; // dp[i] 表示从第 0 到第 i 个元素范围内的最大子数组和
dp[0] = nums[0]; // 初始化 dp[0] 为第一个元素
int result = dp[0]; // 记录最大子数组和,初始化为第一个元素的值

// 遍历数组,从第二个元素开始
for (int i = 1; i < nums.length; i++) {
// 状态转移:比较包含当前元素的子数组和与当前元素的值,取较大者
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
// 更新最大子数组和
result = Math.max(dp[i], result);
}

return result; // 返回最大子数组和
}
}

2.3 分治法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public int maxSubArray(int[] nums) {
return getMaxSubSum(nums, 0, nums.length - 1);
}

private int getMaxSubSum(int[] nums, int left, int right) {
if (left == right) {
return nums[left];
}
int mid = left + (right - left) / 2;
int leftMaxSum = getMaxSubSum(nums, left, mid);
int rightMaxSum = getMaxSubSum(nums, mid + 1, right);
int crossingMaxSum = getCrossingMaxSum(nums, mid, left, right);
return Math.max(Math.max(leftMaxSum, rightMaxSum), crossingMaxSum);
}

private int getCrossingMaxSum(int[] nums, int mid, int left, int right) {
int leftMaxSum = nums[mid];
int tempSum = nums[mid];
for (int i = mid - 1; i >= left; i--) {
tempSum += nums[i];
leftMaxSum = Math.max(leftMaxSum, tempSum);
}

int rightMaxSum = nums[mid + 1];
tempSum = nums[mid + 1];
for (int i = mid + 2; i <= right; i++) {
tempSum += nums[i];
rightMaxSum = Math.max(rightMaxSum, tempSum);
}

return leftMaxSum + rightMaxSum;
}

}
-------------本文结束感谢您的阅读-------------