一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
首先,我们要知道,什么是分治法?分治法有什么用?什么情况下使用?这些就是比较正常的想法了,好啦,我们接下来开始分析。
一,什么是分治法?
将整个问题分解成若干个小问题后再分而治之。如果觉得得到的子问题的规模还是太大,那就继续分解,直到得到的子问题规模达到要求。必要时逐步合并这些子问题的解,从而得到问题的解。
大家是不是觉得很眼熟?
是不是很像递归的过程,规模逐渐减小。所以,一般来说,分治算法一般由递归来实现。因为分治法就是反映的大规模问题和小规模问题之间的关系。
int Max3(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
}
int DivideAndConquer(int List[], int left, int right) {
//分治法求List[left]到List[right]的最小子列和
int MaxLeftSum, MaxRightSum;//存放左右子问题的解
int MaxLeftBorderSum, MaxRightBoderSum;//存放跨分界线的结果
int LeftBorderSum, RightBorderSum;
int center, i;
if (left == right) {//递归的结束条件,子列只有一个数字
if (List[left] > 0)
return List[left];
else return 0;
}
//下面是分的过程
//找到中分点
center = (left + right) / 2;
//递归求两边子列的最大和
MaxLeftSum = DivideAndConquer(List, left, center);
MaxRightBoderSum = DivideAndConquer(List, center + 1, right);
//下面求跨分界线最大子列和
MaxLeftBorderSum = 0;
LeftBorderSum = 0;
for (i = center; i >= left; i--) {
LeftBorderSum += List[i];
if (LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
//左边扫描结束
MaxRightBoderSum = 0;
RightBorderSum = 0;
for (i = center + 1; i <= right; i++) {
RightBorderSum += List[i];
if (RightBorderSum > MaxRightBoderSum)
MaxRightBoderSum = RightBorderSum;
}
//右边扫描结束
//最后进行比较
return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBoderSum);
}
int MaxSubseqsum3(int List[],int N) {
return DivideAndConquer(List, 0, N - 1);
}
二,在线处理
“在线”的意思是指每输入一个数据就进行即时处理,得到的结果是对于当前已经读入的所有数据都成立的解,即在任何地方中止输入,算法都能正确给出正确的解。
这种算法并不要求存储序列中的数据,只需要一个一个读入,同时一个一个处理即可,处理过的数据没必要存储,可以说是最快的算法了。
int MaxSubseqSum4(int List[], int N) {
int i;
int ThisSum, MaxSum;
ThisSum = MaxSum = 0;
for (i = 0; i < N; i++)
{
ThisSum += List[i];
if (ThisSum > MaxSum)
MaxSum = ThisSum;
else if (ThisSum < 0)
ThisSum = 0;
}
return MaxSum;
}
\