最大子序和问题(非常详细,附带源码)
所谓最大子序和问题,就是从给定的整数序列中找到连续的一串整数(至少包含 1 个整数),要求这串整数的和是所有整数串中最大的。
例如,[ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 是一个整数序列,其中和最大的整数串是 [ 4, -1, 2, 1 ],所有整数的和是 6。
再例如,[ -1, 4, -2 ] 是一个整数序列,其中和最大的整数串是 [4],只包含一个整数 4。
最大子序和问题可以用贪心算法解决,接下来就给大家讲解具体的实现思路。
以 [ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 为例,贪心算法查找最大子序和的思路是:从头遍历整个序列,对于每一个元素,如果它的存在有助于找到最大自序和,就把它加入到整形串中;反之则放弃当前元素,继续从下一个元素开始查找最大自序和。
可以看到,遍历过程中找到了很多个整数串,它们都是不同场景下查找最大子序和的最优解,其中最大的和是 6,它就是 [ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 这个序列的最大子序和。
下面是贪心算法解决最大子序和问题的伪代码:
下面是用贪心算法实现最大子序和问题的 Java 程序:
下面是用贪心算法实现最大子序和问题的 Python 程序:
运行程序,执行结果为:
例如,[ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 是一个整数序列,其中和最大的整数串是 [ 4, -1, 2, 1 ],所有整数的和是 6。
再例如,[ -1, 4, -2 ] 是一个整数序列,其中和最大的整数串是 [4],只包含一个整数 4。
最大子序和问题可以用贪心算法解决,接下来就给大家讲解具体的实现思路。
贪心算法解决最大子序和问题
我们知道,贪心算法的核心是每次都选择当下最优的解决方案,又叫局部最优解。以 [ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 为例,贪心算法查找最大子序和的思路是:从头遍历整个序列,对于每一个元素,如果它的存在有助于找到最大自序和,就把它加入到整形串中;反之则放弃当前元素,继续从下一个元素开始查找最大自序和。
| 元 素 | 分 析 | 是否选择 | 整数串 |
|---|---|---|---|
| -2 | -2 是负数,它的存在只会拉低后续元素的总和,不利于找到最大自序和 | 不选 | [ ] |
| 1 | 1 是正数,它可以进一步抬高后续元素的总和,有助于找到最大自序和 | 选 | [1],和为 1 |
| -3 | [1, -3] 的和是 -2,是负数,[1, -3] 的存在只会拉低后续元素的总和,不利于找到最大子序和 | 不选 | [ ] |
| 4 | 4 是正数,它可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4],和为 4 |
| -1 | [4, -1] 的和是 3,是正数,[4, -1] 可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4, -1],和为 3 |
| 2 | [4, -1, 2] 的和是 5,是正数,[4, -1, 2] 可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4, -1, 2],和为 5 |
| 1 | [4, -1, 2, 1] 的和是 6,是正数,[4, -1, 2, 1] 可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4, -1, 2, 1],和为 6 |
| -5 | [4, -1, 2, 1, -5] 的和是 1,是正数,[4, -1, 2, 1, -5] 可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4, -1, 2, 1, -5],和为 1 |
| 4 | [4, -1, 2, 1, -5,4] 的和是 5,是正数,[4, -1, 2, 1, -5,4] 可以进一步抬高后续元素的总和,有助于找到最大子序和 | 选 | [4, -1, 2, 1, -5,4],和为 5 |
可以看到,遍历过程中找到了很多个整数串,它们都是不同场景下查找最大子序和的最优解,其中最大的和是 6,它就是 [ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 这个序列的最大子序和。
下面是贪心算法解决最大子序和问题的伪代码:
maxSubArray(nums):
n <- length(nums) // 获取 nums 序列的元素个数
maxSum <- MIN_INT // 记录最大的子序和,初始值为最小的整数
curSum <- 0 // 记录当前的子序和,初始值为0
// 遍历整个数组
for i<-0 to n:
curSum <- curSum + nums[i]
// 若当前整数串的和大于之前的最大结果,对结果进行更新
maxSum <- max(curSum, maxSum)
// 若当前整数串的和为负,对结果无益,则从 nums[i+1]开始重新查找。
curSum <- max(0, curSum)
return maxSum
贪心算法实现最大子序和问题
下面是用贪心算法实现最大子序和问题的 C 语言程序:
#include <stdio.h>
#include <limits.h>
int maxSubArray(int* nums, int numsSize) {
int n = numsSize; // 获取 nums 序列的元素个数
int maxSum = INT_MIN; // 记录最大的子序和,初始值为最小的整数
int curSum = 0; // 记录当前的子序和,初始值为0
// 遍历整个数组
for (int i = 0; i < n; ++i) {
curSum += nums[i]; // 将当前元素加入当前子序列
// 若当前子序和大于之前的最大结果,更新最大子序和
maxSum = curSum > maxSum ? curSum : maxSum;
// 若当前子序和为负,对结果无益,从 nums[i+1] 开始重新查找
curSum = curSum > 0 ? curSum : 0;
}
return maxSum; // 返回最终结果
}
int main() {
int nums[] = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
int numsSize = sizeof(nums) / sizeof(int);
int result = maxSubArray(nums, numsSize);
printf("最大子序和是 %d\n", result);
return 0;
}
下面是用贪心算法实现最大子序和问题的 Java 程序:
public class MaxSubArray {
public static int maxSubArray(int[] nums) {
int n = nums.length; // 获取 nums 序列的元素个数
int maxSum = Integer.MIN_VALUE; // 记录最大的子序和,初始值为最小的整数
int curSum = 0; // 记录当前的子序和,初始值为0
// 遍历整个数组
for (int i = 0; i < n; ++i) {
curSum += nums[i]; // 将当前元素加入当前子序列
// 若当前子序和大于之前的最大结果,更新最大子序和
maxSum = Math.max(curSum, maxSum);
// 若当前子序和为负,对结果无益,从 nums[i+1] 开始重新查找
curSum = Math.max(curSum, 0);
}
return maxSum; // 返回最终结果
}
public static void main(String[] args) {
int[] nums = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
int result = maxSubArray(nums);
System.out.println("最大子序和是 " + result);
}
}
下面是用贪心算法实现最大子序和问题的 Python 程序:
def maxSubArray(nums):
n = len(nums) # 获取 nums 序列的元素个数
maxSum = float('-inf') # 记录最大的子序和,初始值为负无穷大
curSum = 0 # 记录当前的子序和,初始值为0
# 遍历整个数组
for i in range(n):
curSum += nums[i] # 将当前元素加入当前子序列
# 若当前子序和大于之前的最大结果,更新最大子序和
maxSum = max(curSum, maxSum)
# 若当前子序和为负,对结果无益,从 nums[i+1] 开始重新查找
curSum = max(0, curSum)
return maxSum # 返回最终结果
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
result = maxSubArray(nums)
print("最大子序和是", result)
运行程序,执行结果为:
最大子序和是 6
ICP备案:
公安联网备案: