尋找數組A[low...high]的和最大的非空連續子數組,
採用分治策略:找到子數組的中央位置,將A分爲A[low...mid]和A[mid+1...high],
A[low...high]的任何連續子數組必然是以下三種情況之一:
- 處於子數組A[low...mid]中
- 處於子數組A[mid+1...high]中
- 跨越了中點,有一半在A[low...mid]中,有一半在A[mid+1...high]中,
前兩種情況是規模更小的子問題,第三種單獨處理,然後選三者和最大者。
以上摘自算法導論。。。。。。。。。。。。。。。。。。。。。。。。。。。
代碼實現如下
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<limits.h>
#include<tuple>
using namespace std;
tuple<int,int,int> find_max_crossing_subarray(int a[], int low, int mid, int high)
{
int left_sum = INT64_MIN;
int right_sum = INT64_MIN;
int temp_left = 0;
int temp_right = 0;
int left_index = 0;
int right_index = 0;
for (int i = mid; i >= low; i--)
{
temp_left += a[i];
if (temp_left > left_sum)
{
left_sum = temp_left;
left_index = i;
}
}
for (int i = mid + 1; i <= high; i++)
{
temp_right += a[i];
if (temp_right > right_sum)
{
right_sum = temp_right;
right_index = i;
}
}
int sum = right_sum + left_sum;
auto tp = std::tie(sum, left_index, right_index);
return tp;
}
tuple<int,int,int> find_max_subarray(int a[], int low, int high)
{
if (a == nullptr || low > high)
return make_tuple(0,0,0);
if (low == high)
return make_tuple(a[low],low,high);
int mid = (low + high) / 2;
int i = low;
int j = high;
tuple<int, int, int> tp[3];
tp[0]= find_max_subarray(a, i, mid);
tp[1]= find_max_subarray(a, mid + 1, j);
tp[2]= find_max_crossing_subarray(a, i, mid, j);
int tp_0[3] = { get<0>(tp[0]),get<0>(tp[1]), get<0>(tp[2]) };
int *max = max_element(tp_0, tp_0 + 3);//最後一個元素不做比較,真的坑
int index = max - tp_0;
/*auto temp1 = find_max_subarray(a, low, mid);
auto temp2 = find_max_subarray(a, mid + 1, high);
auto temp3 = find_max_crossing_subarray(a, low, mid, high);*/
return tp[index];
}
int main()
{
int a[17] = { 0,13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 };
auto result=find_max_subarray(a, 1, 16);
auto result1 = find_max_crossing_subarray(a, 1, 8, 16);
cout<<get<0>(result)<<" "<< get<1>(result)<<" "<< get<2>(result);
return 0;
}