暴力+分治+贪心+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
题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...
随机推荐
- pandas 字典创建Dataframe
所有的ndarrays必须具有相同的长度.如果传递了索引(index),则索引的长度应等于数组的长度.如果没有传递索引,则默认情况下,索引为range(n),其中n为数组长度. import pand ...
- django.db.utils.OperationalError: (1366, "Incorrect string value: '\\xE5\\xA4\\xAB\\xE4\\xBA\\xBA' f
1.打开mysql命令行 show variables like '%char%'; 将字符集显示不是utf-8的更改为utf-8 例如:set character_set_database=utf8 ...
- Oracle 11gR2 单实例 For linux6
第一章 准备工作 1.1 系统硬件和软件环境检查 Ø 物理内存至少1G # grep MemTotal /proc/meminfo Ø swap物理内存小于2G时设置为物理内存 ...
- [etcd]简介与安装
简介 etcd是一个采用Raft协议实现强一致性的分布式键值数据库,它提供了一种可靠的方式存储需要被分布式系统或机器集群访问的数据. 常见使用场景:服务注册与发现.键值对存储.消息发布和订阅.分布式锁 ...
- 【go笔记】从安装到helloworld
前言 Go语言也称Golang,google出品,特点在于编程简便的同时并发性能不俗. 环境准备: Go语言版本:1.17.2.安装包下载链接:https://studygolang.com/dl l ...
- Spring Secriuty登录失败错误状态999重定向302
原因是login.html登录页面有不能加载的静态资源,找出来去掉就好了,比如 bootstrap.min.css 环境 使用Spring Boot Security 3做一个登录功能,使用了一个教程 ...
- 大怨种的pwn的wp
0x01 pwnable_echo1 军训几天加暑假的活 from pwn import * context(os='linux', arch='amd64', log_level='debug') ...
- ES集群&kibana安装
一.elasticsearch介绍 Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负 ...
- selenium库浅析
selenium库浅析 基于4.3 pip install selenium安装好后,在sitepackages下 2个主要的目录,common和webdriver 1- common 该目录一共就一 ...
- 2023.09.29 入门级 J2 模拟赛 赛后总结(尝试第一篇总结)
T1:变换(change) 一道大水题. 赛场上想都没想就切掉了 不难发现,转换的过程只和a 和b 的二进制位有关,且不同二进制位之间无关.我们可以将a 和b 转化为二进制表示,每一位分别判断,如果这 ...