最大子数组问题 C++分治与动态规划求解

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);
}

算法分析:

  1. 分治递归策略。将数组依次二分以缩减问题规模,拿第一次二分来说,如果整个数组存在一个最大子数组,那么它要么在划分后的左半部分,要么在右半部分,要么跨过中线,正是依据这个思路我们将问题一直缩减,缩减到单个元素时为base case。在一次划分返回时,返回这三种情况中最大的值以及当前这一个最大子数组(不一定是全局最大的)所覆盖的范围(下标起始位置与终止位置),最终在最后一次返回(也就是第一次划分)时得到我们要的结果。
  2. 因为采用分治递归策略,算法时间复杂度为O(nlgn)

2.动态规划解法

代码如下:

#include <iostream>
using namespace std;

class dpFindMaxSubArr {
   
private:
	int *arr, *dp;
	int size;
	int minPos, maxPos, maxValue;
<
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值