0.问题定义
1.分治解法
代码如下:
#include <iostream>
using namespace std;
struct info {
int sum, low, high;
info(int sum_, int low_, int high_) : sum(sum_), low(low_), high(high_) {}
};
class maxSubarrayProblem {
private:
int *arr;
int size;
public:
maxSubarrayProblem(int *arr_, int size_) {
arr = new int[size = size_];
for (int i=0; i<size; ++i)
arr[i] = arr_[i];
info res = findMaxSubArr(0, size-1);
cout << "result is:" << res.low << " to " << res.high << " sum as " << res.sum;
}
info findMaxSubArr(int low, int high) {
if (low==high) // base case
return info(arr[low], low, high);
int mid = (low+high)/2;
info lh = findMaxSubArr(low, mid);
info rh = findMaxSubArr(mid+1, high);
info mh = findCroSubArr(low, mid, high);
// choose biggest to return
if (lh.sum>rh.sum && lh.sum>mh.sum)
return lh;
else if (rh.sum>lh.sum && rh.sum>mh.sum)
return rh;
else
return mh;
}
info findCroSubArr(int low, int mid, int high) {
int ls = 0, rs = 0, lp = 0, rp = 0;
int lm = arr[mid]-1, rm = arr[mid+1]-1;
// left side max value
for (int i=mid; i>=low; --i) {
ls += arr[i];
if (ls>lm) {
lp = i;
lm = ls;
}
}
// right side max value
for (int i=mid+1; i<=high; ++i) {
rs += arr[i];
if (rs>rm) {
rp = i;
rm = rs;
}
}
// get and return crossing middle max value.
return info(lm+rm, lp, rp);
}
};
int main() {
// 7-10 43
int a[]{13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5,
-22, 15, -4, 7};
maxSubarrayProblem test(a, 16);
}
算法分析:
- 分治递归策略。将数组依次二分以缩减问题规模,拿第一次二分来说,如果整个数组存在一个最大子数组,那么它要么在划分后的左半部分,要么在右半部分,要么跨过中线,正是依据这个思路我们将问题一直缩减,缩减到单个元素时为base case。在一次划分返回时,返回这三种情况中最大的值以及当前这一个最大子数组(不一定是全局最大的)所覆盖的范围(下标起始位置与终止位置),最终在最后一次返回(也就是第一次划分)时得到我们要的结果。
- 因为采用分治递归策略,算法时间复杂度为O(nlgn)
2.动态规划解法
代码如下:
#include <iostream>
using namespace std;
class dpFindMaxSubArr {
private:
int *arr, *dp;
int size;
int minPos, maxPos, maxValue;
<