非常经典的问题了,大题意思就是一串数组里面有正有负,求加起来最大的子数组。例如:
{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}
最大子数组为:
{18,20,-7,12}
我在这里只是为了学习分治,所以那个复杂度O(n^2)的那个就不再多说。直接进入正题,用分治来解决。
分析:
三种情况:
1.完全位于子数组A[left,mid],i,j∈[left,mid];
2.完全位于子数组B[mid+1,right],i,j∈(mid,right];
3.跨越中点,i∈[left,mid];j∈(mid,right];
可以将问题分为最终左右数组大小为1的情况,然后合并,这样层层递归。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int Max(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
}
int go(int *List, int left, int right) {
int maxleft, maxright;
int maxleft_1, maxright_1;
int left_1, right_1;
int mid, i;
if (left == right) {//这里就是底层了,不要判定正负,我加了反正是不出结果,毕竟只有一个数的情况下,这个数就是最大值。
return List[left];
}
mid = (left + right) / 2;
maxleft_1 = 0, maxright_1 = 0, left_1 = 0, right_1 = 0;
for (i = mid; i >= left; i--) {
left_1 += List[i];
if (left_1 > maxleft_1)
maxleft_1 = left_1;
}
for (i = mid + 1; i <= right; i++) {
right_1 +=List[i];
if (right_1 > maxright_1)
maxright_1 = right_1;
}
maxleft = go(List, left, mid);
maxright = go(List, mid + 1, right);
return Max(maxleft, maxright, maxleft_1 + maxright_1);
}
int main(void) {
int n; cin >> n;
int *List = new int[n];
for (int i = 0; i < n; i++)
cin >> List[i];
cout<<go(List, 0, n - 1);
system("pause");
return 0;
}
还有种方法是动态规划,一趟过的那种,这里我在加一条记录起始最大子数组起始位置的条件
#include <iostream>
using namespace std;
int FindMaxSubarray(int array[], int length)
{
int start = 0, end = 0; //记录最大子数组的起始位置(在数组中的下标)
int MaxSumSub; //最大子数组的值
int* dp = new int[length]; //动态规划记录
dp[0] = array[0]; //初始为第一个数
MaxSumSub = dp[0]; //最大值初始为第一个数
int temp = 0; //
for(int i = 1; i < length; i++)
{
if(dp[i - 1] <= 0) //前面的<0,直接丢弃
{
dp[i] = array[i];
temp = i; //记录起始为止
}
else
dp[i] = array[i] + dp[i - 1]; //往后求和
if(dp[i] > MaxSumSub) //找到到i为止的最大子数组
{
MaxSumSub = dp[i]; //最大...
start = temp; //标记起始
end = i; //标记此时的结束位置
}
}
cout<<"最大子序列的下标:"<<start<<"->"<<end<<endl;
return MaxSumSub;
}
int main()
{
int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
//int a[] = {23, 4};
int length = sizeof(a) / sizeof(int);
cout<<FindMaxSubarray(a, length);
return 0;
}