暴力+分治+贪心+DP:最大子序列和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6
暴力:暴力列举所有可能的连续子数组,算法复杂度O(N^3)
算法1:
1 int MaxSubseqSum1(int A[], int N)
2 {
3 int ThisSum, MaxSum = 0;
4 int i,j,k;
5
6 for (i = 0; i < N; i++) //i对应子列左端位置
7 {
8 for (j = i; j < N; j++) //j对应子列右端位置
9 {
10 ThisSum = 0;
11 for (k = i; k <= j; k++) //一段子列的和
12 {
13 ThisSum += A[k];
14 }
15 if(ThisSum > MaxSum)
16 MaxSum = ThisSum; //更新
17 }
18 }
19 return MaxSum;
20 }
每次从i加到j,我们都必须要经历k循环,i+(i+1)...j,所以每次j循环后都要经历一个k循环从i加到j,想想完全没有必要,可以直接在前一个子序
列的基础上加一个元素,所以k循环是没有必要的。
因此优化算法在相同的i不同的j只需要在j-1次的循环的基础上累加一项即可,算法复杂度更新为O(N^2)
算法2:
1 int MaxSubseqSum2(int A[], int N)
2 {
3 int ThisSum, MaxSum = 0;
4 int i,j,k;
5
6 for (i = 0; i < N; i++) //i对应子列左端位置
7 {
8 ThisSum = 0;
9 for (j = i; j < N; j++) //j对应子列右端位置
10 {
11 ThisSum += A[k]; //在上一个子序列和的基础上加一个数
12
13 if(ThisSum > MaxSum)
14 MaxSum = ThisSum;
15 }
16 }
17 return MaxSum;
18 }
算法3:分治把大问题拆成小问题,然后逐个解决,最后合并起来。
把数组一分为二,分别递归(即左右两边再分成小的左右两边)的去解决左右两边问题,得到两边的最大子列和,还有一种情况跨越边界的最大子列和,然后想要的结果就是这三个数之间的最大的那个数。算法复杂度O(NlogN)
1 int Max3( int A, int B, int C )
2 { /* 返回3个整数中的最大值 */
3 return A > B ? A > C ? A : C : B > C ? B : C;
4 }
5
6 int DivideAndConquer( int List[], int left, int right )
7 { /* 分治法求List[left]到List[right]的最大子列和 */
8 int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */
9 int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界线的结果*/
10
11 int LeftBorderSum, RightBorderSum;
12 int center, i;
13
14 if( left == right ) { /* 递归的终止条件,子列只有1个数字 */
15 if( List[left] > 0 ) return List[left];
16 else return 0;
17 }
18
19 /* 下面是"分"的过程 */
20 center = ( left + right ) / 2; /* 找到中分点 */
21 /* 递归求得两边子列的最大和 */
22 MaxLeftSum = DivideAndConquer( List, left, center );
23 MaxRightSum = DivideAndConquer( List, center+1, right );
24
25 /* 下面求跨分界线的最大子列和 */
26 MaxLeftBorderSum = 0; LeftBorderSum = 0;
27 for( i=center; i>=left; i-- ) { /* 从中线向左扫描 */
28 LeftBorderSum += List[i];
29 if( LeftBorderSum > MaxLeftBorderSum )
30 MaxLeftBorderSum = LeftBorderSum;
31 } /* 左边扫描结束 */
32
33 MaxRightBorderSum = 0; RightBorderSum = 0;
34 for( i=center+1; i<=right; i++ ) { /* 从中线向右扫描 */
35 RightBorderSum += List[i];
36 if( RightBorderSum > MaxRightBorderSum )
37 MaxRightBorderSum = RightBorderSum;
38 } /* 右边扫描结束 */
39
40 /* 下面返回"治"的结果 */
41 return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );
42 }
43
44 int MaxSubseqSum3( int List[], int N )
45 { /* 保持与前2种算法相同的函数接口 */
46 return DivideAndConquer( List, 0, N-1 );
47 }
算法4:贪心算法(在线处理算法)
每输入一个数据,进行即时处理,在任何一个地方停止输入,算法都能得到正确的解,即总是做出在当前看来最好的选择。
只需遍历一遍数组,算法复杂度为O(N)。
1 int MaxSubseqSum4(int A[], int N)
2 {
3 int i;
4 int ThisSum, MaxSum;
5 ThisSum = MaxSum = 0;
6
7 for (i = 0; i < N; i++) //向右累加
8 {
9 ThisSum += A[i];
10 if (ThisSum > MaxSum)
11 MaxSum = ThisSum; //发现更大则更新
12 else if (ThisSum > MaxSum) //如果当前子序列为负,因为它不能使后边子列和增大
13 ThisSum = 0; //直接放弃累加
14 }
15 return MaxSum;
16 }
算法5:动态规划(DP)
不断更新dp[i]中的值,表示A数组中以A[i]为结尾的最大子序列和,例如A = [2,3,-6,2,4],则dp = [2,5,-1,2,6],则dp数组中的最大值就是最大子序列和就是6.
只需要遍历一遍数组,算法复杂度O(N)
1 int MaxSubseqSum1(int A[], int N)
2 {
3 int i;
4 int dp[N];
5 int ThisSum = 0;
6 dp[0] = A[0];
7 for (i = 1; i < N; i++)
8 {
9 if (dp[i]<0 || (i==1 && dp[0]<0)) //如果A[0]就小于0则它并不能使后边序列增大所以不累加,或者后边的子序列和中出现负值
10 {
11 dp[i] = A[i];
12 }
13 else
14 {
15 dp[i] = dp[i - 1] + A[i];
16 }
17 }
18
19 return Max.dp[i];
20 }
DP是根据自己的理解写的,如有不对,请指正谢谢。
暴力+分治+贪心+DP:最大子序列和的更多相关文章
- BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP
BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...
- D. Diverse Garland Codeforces Round #535 (Div. 3) 暴力枚举+贪心
D. Diverse Garland time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- hdu 1257 最少拦截系统【贪心 || DP——LIS】
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP
洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...
- 【BZOJ-3174】拯救小矮人 贪心 + DP
3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 686 Solved: 357[Submit][Status ...
- 洛谷P4823 拯救小矮人 [TJOI2013] 贪心+dp
正解:贪心+dp 解题报告: 传送门! 我以前好像碰到过这题的说,,,有可能是做过类似的题qwq? 首先考虑这种显然是dp?就f[i][j]:决策到了地i个人,跑了j个的最大高度,不断更新j的上限就得 ...
- 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp
题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...
- 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp
题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...
- 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp
题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的 ...
- 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp
题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...
随机推荐
- IIC总线学习笔记
IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板.嵌入式系统或手 ...
- java无法加载maper.xml问题
项目依赖其他模块,模块中有 mapper,本项目也有mapper,导致项目无法正常运行. 解决办法: 1.配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.X ...
- React: 路由重定向
解决方案 参考链接 https://v5.reactrouter.com/web/example/route-config
- win10安装mysql-8.0.19-winx64
第一步:去官网下载安装 (重点)第二步:先解压,然后在mysql下创建一个my.ini文件,更改my.ini文件里面的两行安装目录,第二行加上\data,my.ini文件不能多或少一个符号,内容见文章 ...
- OpenCV实战:从图像处理到深度学习的全面指南
本文深入浅出地探讨了OpenCV库在图像处理和深度学习中的应用.从基本概念和操作,到复杂的图像变换和深度学习模型的使用,文章以详尽的代码和解释,带领大家步入OpenCV的实战世界. 1. OpenCV ...
- 推荐工具!使终端便于 DevOps 和 Kubernetes 使用
如果你熟悉 DevOps 和 Kubernetes 的使用,就会知道命令行界面(CLI)对于管理任务有多么重要.好在现在市面上有一些工具可以让终端在这些环境中更容易使用.在本文中,我们将探讨可以让工作 ...
- Health Kit基于数据提供专业方案,改善用户睡眠质量
什么是CBT-I? 中国社科院等机构今年发布的<中国睡眠研究报告2023>内容显示,2022年,受访者的每晚平均睡眠时长为7.40小时,近半数受访者的每晚平均睡眠时长不足8小时(47.55 ...
- 如何在linux上安装neovim0.9(以debian和ubuntu为例) – 东凭渭水流
发布于 1 分钟前 3 次阅读 由于apt中只有neovim-0.72的安装包.想使用新版需要自己安装,以下是安装过程 1.首先需要卸载旧版neovim sudo remove neovim 2.从 ...
- Go Web项目结构 + 基础代码
Go Web工程 下面是项目的包图,可以通过包图来理清项目包的结构. Go Web工程 下面是项目的包图,可以通过包图来理清项目包的结构. 因为我是从Java转过来的,其实这种包的结构与Java的类似 ...
- Postgresql 批量插入命令COPY使用
在很多场景下,我们经常会遇到将某个Excel或Csv文件中的数据,插入到Postgresql.对于这个需求,我们常规的处理办法就是将文件中的数据,按照文件表头名称转换成集合对象然后插入到数据库,当然这 ...