暴力+分治+贪心+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
题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...
随机推荐
- go语言全景俯瞰
本篇是语言教学的"传统项目".每个写go语言教学的人,都会介绍它的发展历程,应用领域,优缺点和特点来介绍自己的理由.当然如果你有自己的理解,那就更好了,欢迎讨论! 全景简介 go语 ...
- CSS: 绝对定位fixed
属性介绍 元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置.元素的位置在屏幕滚动时不会改变.打印时,元素会出现在的每页的固定位置.fi ...
- WebStorm: 配置React中useState自动补齐功能
配置如下 模板文本如下所示 const [$STATE$, $SET_STATE$] = useState($INITAL_STATE$) 编辑变量 SET_STATE文本如下所示 concat(&q ...
- QLabel标签快捷键的使用
1 from PyQt5.QtWidgets import * 2 import sys 3 4 class QlabelDemo(QDialog): 5 def __init__(self): 6 ...
- cesium加载gif图片(cesium篇.43)
https://blog.csdn.net/QQ98281642/article/details/120214325
- 静态vlan的划分实验
静态vlan的划分 1,toupu图 2,配置id与子网掩码 2.1,pc,server的ip与子网配置 pc5 pc6 pc7 pc8 server1 server2 3,vlan的静态划分 1,v ...
- 关于Openssh版本升级问题及版本升级到最新版8.7p1流程(CentOS7系统)
前言: 对linux服务器做过漏洞扫描的都知道,常常服务器会被扫出一大堆关于openssh的漏洞,诸如下面这些,而其中的原因就是因为openssh版本比较低.于是就需要升级openssh的版本.下面就 ...
- Elasticsearch 保姆级入门篇
Elasticsearch 是一个分布式的.面向生产规模工作负载优化的搜索引擎. Kibana 可以将 Elasticsearch 中的数据转化为直观的图表.图形和仪表盘. 这篇文章,您将学习本地安装 ...
- U盘目录穿越获取车机SHELL - 分析与复现
github上破解日系车机的文章 - https://github.com/ea/bosch_headunit_root 其中有利用 U 盘获取车机 shell 的操作 主要根据下面这篇文章进行环境搭 ...
- 在centos7.X下安装Java
发布于 2 分钟前 2 次阅读 1.创建JDK目录 mkdir /opt/jdk 2.通过finalshell或xftp将jdk上传到/opt/jdk目录中 3.cd /opt/jdk 4.解压jd ...