对于数组ai,最大子数组定义为:ai的和最大的非空连续子数组,很明显,这个概念只对既有正元素,又有负元素的数组有意义,例如,对于ai[16] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7},最大子数组为{18, 20, -7, 12},此时的和为43,求解一个数组的最大子数组的算法依然是使用分治思想,把一个数组一分为二,最大子数组要么在左边,要么在右边,要么在中间,在中间则肯定包含中点,此时便可以从中点的左边和右边分别求出最大子数组的边界,合起来便是最大子数组,然后递归的调用此方法,便可求出原数组的最大子数组。
代码如下:
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
int* find_max_crossing_subarray ( vector<int> &ci, unsigned low, unsigned mid, unsigned high); //函数返回数组的指针
int* find_maximum_subarray (vector<int> &ci, unsigned low, unsigned high);
//函数返回数组的指针
//函数的功能为寻找横跨中点的最大子数组的小标和和,并组成一个数组返回
int* find_max_crossing_subarray ( vector<int> &ci, unsigned low, unsigned mid, unsigned high)
{
int *temp = new int[3]; //为防止局部变量内存被释放掉,采用动态分配内存
int left_sum = -1000;
int right_sum = -1000;
int sum = 0;
unsigned max_left = 0;
unsigned max_right = 0;
for (int i = mid; i >= 0 && i >= low ; --i)
{
sum = sum + ci[i];
if(sum > left_sum )
{
left_sum = sum;
max_left = i;
}
}
sum = 0;
for (unsigned j = mid + 1; j <= high; ++j)
{
sum = sum + ci[j];
if(sum > right_sum )
{
right_sum = sum;
max_right = j;
}
}
temp[0] = max_left;
temp[1] = max_right;
temp[2] = left_sum + right_sum;
return temp;
}
//函数返回数组的指针
//函数的功能为寻找一个数组的最大子数组的下标和和
int* find_maximum_subarray (vector<int> &ci, unsigned low, unsigned high)
{
int *temp_1 = new int[3]; //为防止局部变量内存被释放掉,采用动态分配内存
if (low == high)
{
temp_1[0] = low;
temp_1[1] = high;
temp_1[2] = ci[low];
return temp_1;
}
else
{
int mid = (low + high) / 2;
int *temp_left = new int[3];
int *temp_right = new int[3];
int *temp_cross = new int[3];
temp_left= find_maximum_subarray(ci, low,mid);
temp_right= find_maximum_subarray(ci, mid+1,high);
temp_cross= find_max_crossing_subarray ( ci, low,mid,high) ;
if (temp_left[2] > temp_right[2] && temp_left[2] > temp_cross[2] )
{
return temp_left;
}
else
{
if ( temp_right [2] > temp_left[2] && temp_right[2] > temp_cross[2] )
{
return temp_right;
}
else
{
return temp_cross;
}
}
}
}
int main ()
{
vector<int> ai;
int num = 0;
cout << "please enter the numbers that need to find the maximum subarray:" << endl;
while (cin >> num )
ai.push_back(num);
int* maximum_subarray = find_maximum_subarray(ai,0,ai.size () - 1);
cout << maximum_subarray[0] << "\t"
<< maximum_subarray[1] << "\t"
<< maximum_subarray[2] << "\t"
<< endl;
delete[] maximum_subarray;
return 0;
}
运行结果为:
上述结果表示为最大子数组为ai[7]到ai[10],此时和为43。
上述代码可能存在内存分配的问题,C++的学习进度还没到这一块,因此还没解决这个问题。
不得不说算法的力量是无穷的,或者说思想的力量是伟大的。
夜深了,你在干嘛呢?