最大子段和,二分法变异,动态规划
来源:互联网 发布:幽游白书 知乎 编辑:程序博客网 时间:2024/05/17 02:03
先描述“最大子段和”的概念,然后用分治法和动态规化来解决,最后添加一些功能。
对于n个元素的整数数列(可能还有负整数),求任意连续m个数(m<=n),使其和为最大。如果该子段均为负数,定义其和为0.
比如{-2 11 -4 13 -5 -2},的最大子段和为{11,-4,13},其和为20。
该问题不能采用简单的分治法来解决,比如上面的数组分成{-2,11,-4}和{13,-5,-2}后,一个子问题的解是11,另一个是13,然而都不可能达到最终解。
所以这个问题的两个子问题不是相互独立的,需要涉及子问题的交互。故采用变异的二分法来处理。
intmaxSub_binary(constv ector<int> &nums,intleft,intright){
if(left==right)returnnums[left]> 0 ? nums[left]: 0;//处理只有一个数字的情况。
intmid = (left + right)>> 1;//分为两部分
intmaxSum_left = maxSub_binary(nums,left,mid);//左边递归求解
intmaxSum_right = maxSub_binary(nums, mid +1, right);//右边递归求解
//处理脚踩两条船的子段
intleftSum(0);
for(inti(mid), tmpSum(0); i >=left; --i) {
tmpSum+=nums[i];
if(tmpSum > leftSum)leftSum = tmpSum;
}//for i
intrightSum(0);
for(inti(mid + 1), tmpSum(0); i <=right; ++i) {
tmpSum+=nums[i];
if(tmpSum > rightSum)rightSum = tmpSum;
}//for i
//比较子段和的大小,选择返回哪一部分的子段和
intmaxSum_twoParts = leftSum + rightSum;
if(maxSum_twoParts < maxSum_left&&maxSum_right < maxSum_left)returnmaxSum_left;
if(maxSum_twoParts < maxSum_right)returnmaxSum_right;
returnmaxSum_twoParts;
}//maxSub_binary
如果分治法的子问题不能相互独立,也就是子问题相互重叠的情况,一般采用动态规划法来解决。
int maxSub_dp(constvector<int> &nums) {
intret(0);
intlen = (int)nums.size();
vector<int> dp(len, 0);
dp[0]=nums[0];
for(inti(1); i < len; ++i) {
if(dp[i - 1]> 0)dp[i]= dp[i - 1]+nums[i];
elsedp[i]=nums[i];
if(dp[i]> ret)ret = dp[i];
}//for i
returnret;
}//maxSub_dp
下面的代码在之前函数的基础上,进一步得到最大子段和的长度,注意长度信息的添加位置。
由于maxSub_len_binary的返回值用来返回最大子段和的值,只能将长度信息反映在一个引用参数curLen上了。
maxSub_len_dp也是类似处理。
int maxSub_len_binary(constvector<int> &nums,intleft,intright,int&curLen) {
if(left==right) {
curLen= 1;
returnnums[left]> 0 ? nums[left]: 0;
}//if
intmid = (left + right)>> 1;
intleftLen(0);
intmaxSum_left = maxSub_len_binary(nums,left,mid, leftLen);
intrightLen(0);
intmaxSum_right = maxSub_len_binary(nums, mid +1, right, rightLen);
intleftSum(0), leftPartLen(0);
for(inti(mid), tmpSum(0), tmpPartLen(0); i >=left;--i) {
tmpSum+=nums[i];
++tmpPartLen;
if(tmpSum > leftSum)leftSum = tmpSum, leftPartLen = tmpPartLen;
}//for i
intrightSum(0), rightPartLen(0);
for(inti(mid + 1), tmpSum(0), tmpPartLen(0); i <=right;++i) {
tmpSum+=nums[i];
++tmpPartLen;
if(tmpSum > rightSum)rightSum = tmpSum, rightPartLen = tmpPartLen;
}//for i
intmaxSum_twoParts = leftSum + rightSum;
if(maxSum_twoParts < maxSum_left&&maxSum_right < maxSum_left) {
curLen= leftLen;
returnmaxSum_left;
}//if
if(maxSum_twoParts < maxSum_right) {
curLen= rightLen;
returnmaxSum_right;
}//if
curLen= leftPartLen + rightPartLen;
returnmaxSum_twoParts;
}//maxSub_len_binary
int maxSub_len_dp(constvector<int> &nums,int&curLen) {
intret(0);
intlen = (int)nums.size();
vector<int> dp(len, 0);
dp[0] =nums[0];
inttmpLen(1);
for(inti(1); i < len; ++i) {
if(dp[i - 1] > 0)dp[i] = dp[i - 1] +nums[i],++tmpLen;
elsedp[i] =nums[i], tmpLen = 1;
if(dp[i] > ret)ret = dp[i],curLen =tmpLen;
}//for i
returnret;
}//maxSub_len_dp
Gentle Dong,Second Version,20170224
- 最大子段和,二分法变异,动态规划
- 动态规划----最大子段和
- 最大子段和(动态规划)
- 最大子段和动态规划实现
- 最大子段和(动态规划)
- 【动态规划】最大m子段和
- 动态规划 - 最大子段和
- 最大子段和-分治&&动态规划
- 动态规划求解最大子段和
- 动态规划之最大子段和
- 动态规划求最大子段和
- 动态规划之最大子段和
- 动态规划,最大子段和
- 动态规划 最大子段和问题
- 动态规划求最大子段和
- java动态规划最大子段和
- 动态规划:求最大子段和
- 动态规划:最大子段和
- 在左侧的project目录中 看不到项目的文件结构图 只能看到几个idea自己生成的文件
- LeetCode 292. Nim Game
- vbscript 脚本-批量添加AD域测试账号
- sqlserver索引语法
- 把二元查找树转变成排序的双向链表
- 最大子段和,二分法变异,动态规划
- springmvc 配置文件适应部署环境
- 数据不平衡处理----smote算法
- 阿里音乐流行趋势预测大赛一起做-(6)小结
- 《Head first设计模式》学习笔记 - 单件模式
- C++中的explicit关键字
- 中国剩余定理编程实现
- 阿里音乐流行趋势预测大赛一起做-(7)初赛总结之用户分类
- 配置tomcat的https访问