分治法 —— 最大子序和 ( 归并排序应用1)
程序员文章站
2022-07-03 12:29:00
...
LeetCode 最大子序和
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
本题有四种解法,暴力, 动态规划, 分治法 以及 贪心法。
每种解法各有千秋,此处主要讲解分治法如何实现
最大值产生于红色部分, 绿色部分以及蓝色部分三者之间
如何求红色,绿色,蓝色三个part各自的最大值呢?
看图可知,每一个颜色的part都可以分解小规模问题。例如图中的红色part再可以分为红,绿,蓝三个part, 接着继续分继续分继续分 直到红色part和绿色part仅有一个元素时停止
大规模问题转化为小规模问题,最后每个小规模问题解合并即是大规模问题解
即是分治策略
我们知道是分治策略,那如何编程实现呢?
class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
return maxSub(nums, 0, len - 1);
//传入数组,数组起始和末尾位置下标
}
public int maxSub(int[] nums, int left, int right)
{
if (left == right)//递归边界,红色和绿色part仅有一个元素
return nums[left];
int mid = (left + right) / 2;
int leftmax = maxSub(nums, left, mid);//递归进入红色part
int rightmax = maxSub(nums, mid + 1, right);//递归进入绿色part
int leftcrossmax = Integer.MIN_VALUE;
//先置蓝色部分最大值变量为最小值
int leftsum = 0;
//蓝色part至少包括mid 和 mid + 1两个位置的元素值
for (int i = mid; i >= left; i--)
{//进入mid左边寻找最大值
leftsum += nums[i];
if (leftsum > leftcrossmax)
leftcrossmax = leftsum;
}
int rightcrossmax = Integer.MIN_VALUE;
int rightsum = 0;
for (int i = mid + 1; i <= right; i++)
{//进入mid + 1右边去寻找最大值
rightsum += nums[i];
if (rightsum > rightcrossmax)
rightcrossmax = rightsum;
}
int crossmax = rightcrossmax + leftcrossmax;
//mid左边最大值和mid + 1右边最大值以及
//mid 和mid +1 两个位置元素值加起来即是蓝色part的最大值
return Math.max(crossmax, Math.max(leftmax, rightmax));
//总的最大值即是红色part,绿色part以及蓝色part三者最大值中的最最最大值
}
}
上一篇: 嵌入式课程设计 —— GPIO接口编程