homework-01 最大子串和
题目描述
对于一个给定的数列,求该数列最大的子串和(连续)
问题分析
处理发生区间上的问题时,经常会用一个非常简单经典的思路——部分和(也有叫前缀和)。部分和的思想在很多复杂的区间上的算法中都有应用,它解决的问题是,在一个序列a[1..n]中快速求得任意子串a[n] + a[n + 1] + ... a[n + m]的和,具体过程非常简单,在原序列里,a[i]保存了在序列中第i个位置的数值,根据原序列生成一个新数列s[1..n],其中s[j] = sum{a[i], 0 <= i <= j},那么对于任意子串和就有a[p..q]=s[q]-s[p-1]。这样以来我们就可以在相同的空间复杂度下快速访问更多信息,这样完全不用保留原数组,因为对于任意原数组中的数值都有a[i] = s[i]-s[i-1]。有了新工具我们再来考虑原问题,先从最简单的思路,问题要求找出最大子串和,那么就枚举每一个子串的起始位置,找一个最大的子串,公式表示就是ans=max{s[j]-s[i],0<=i<=j,0<j<=n},从这个式子可以发现,任意子串和都有sum=s[j]-s[i],(0<=i<=j)的形式,其中s[j]的数值固定不同,那么我们只需要找到min{s[i],0<=i<j}就能找到以j结尾最大的子串,这个工作只要的经过简单的预处理就可以得到,那么我们最后实际需要做的工作就是枚举一遍子串的结尾点,结算该结尾最大的子串,并统计其中最大值即可,时空复杂度均为O(n)。
除了以上解法,我还在其他同学的博客发现了一些其他更好的解法,事实上我们发现一个序列里的数有正有负,其中最大子串是其中一些连续的数,这些数也是有正有负的,但其中真正“做出贡献”的只有正数,我们选取了一段负数是因为在这段负数的前后必定有贡献比其损失更多的正数,所以可以简单地得到一个结论,最大子串首尾必须是正数,(如果有一段时负数的话那么去掉这一段得到的子串比原来更大,与假设矛盾)。根据这个结论我们可以得到一个新的算法,把原数列分成正数段和负数段
原序列:
a=[1 - - - - 5]
划分后:
() (- -) ( ) (- -) ( )
b=[1 - - 12]
在新数列上我们枚举每一正数作为起点,然后不断加上他的后继,若当前结果优于已得到的答案则更新答案,当加入一个后继发现当前结果小于等于0时,就结束这次操作找下一个正数迭代。先在简单证明一下它的合理性,前面已经说明了最大子串肯定开始与正数,那么仅需证在每次枚举起始点的操作中都考虑到了所有情况,假设当前起始点为i,结尾枚举到了j时发现b[i..j]<=0,那么对于任意以j+1起始的子串来说,b[i..j] + b[j..k] < b[j..k],因此吧b[i..k]不会比b[j..k]更优,无需进行后面的枚举,证毕。但是现在看来这个算法最坏的时间复杂度是O(n^2),比前者逊色不少,但是这个算法还能再优化,如果以第i个位置为起点的查找到j点结束了,且存在一个b[k]>0,i<k<j,那么对于任意b[k..m],b[i..m]都会比b[k..m]优,因为在枚举过程中保证了b[i..k]>0,同时也保证了b[k..j]<0,那么当我们枚举到j结束之后以j+1处的元素为起始点继续枚举即可,如果全是非正数的话输出最大元素即可,这样这个算法就达到了O(n)的时间复杂度,达到了和前面算法一样的效率。
一些讨论
第二个算法想写上转载地址,但是实在懒得找了,原作者介意的话请速与我联系。在原博中作者自语此法为奇技淫巧(大概同意,忘了原话了),与标准答案略有差距,我个人还是非常喜欢这种接法的, 通过发现问题的新的性质来解决问题本身就会加深对问题的理解,同时带来新的启发,而且这种方法同表程相比代码长度,时空复杂度,思维难度大体相当,没有孰优孰劣之分。有了这些方法原题目现在看上去就so easy了,我们可以简单思考一下扩展问题。
求最小子串和;只需简单给每个数转换正负。
序列尾部会增加或删除元素;在第一种方案中给每个点记录一下当前状态,增删后从断点继续计算即可。
序列长度固定,其中一些元素的值会改变;可以使用标程中O(nlogn)的算法,将每次计算的节点信息保留,元素改变后同时改变影响的节点,时间复杂度为O((m+n)logn),其中m为改变的次数。
序列内部的元素会删除增加,没有想到什么更好的办法。
最大子串积,。。。。。
模m下的最大子串积,。。。。。
其他
我选择的参考书是第二版的《代码大全》
homework-01 最大子串和的更多相关文章
- 【做题】CF1045(ABH)
原文链接https://www.cnblogs.com/cly-none/p/9697662.html 题目当然不会做完了,这里只讲有做&会做的. A. Last chance 题意:有\(n ...
- HDU-1041-Computer Transformation,大数递推,水过~~
Computer Transformatio ...
- 1393 0和1相等串 51nod
1393 0和1相等串 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 给定一个0-1串,请找到一个尽可能长的子串,其中包含的0与1的个数相等. I ...
- LOJ 3184: 「CEOI2018」斐波那契表示法
题目传送门:LOJ #3184. 题意简述: 题目说得很清楚了. 题解: 首先需要了解「斐波那契数系」为何物. 按照题目中定义的斐波那契数列 \(F_n\),可以证明,每个非负整数 \(n\) 都能够 ...
- 【USACO 3.1】Contact(01子串按出现次数排序)
题意:给你一个01字符串,将长度为a到b之间(包含a.b)的子串按照出现次数排序.注意输入输出格式 题解:01子串对应一个二进制,为了区别11和011这样的不同子串,我们把长度也记录下来,官方题解是在 ...
- 2019牛客暑期多校赛(第三场)B-求01串中的最长01数量相等的子串和子序列
https://ac.nowcoder.com/acm/contest/883/B 首先先把0所在的位置变-1,1所在位置变1,然后统计一个前缀和,用sum[i]表示. 那么如果从起点开始的话只要满足 ...
- Java实现固定长度得01子串
固定位数得01子串 Description 对于长度为n的一个01串,每一位都可能是0或1,一共有2 ^n 种可能.请按从小到大的顺序输出这2^n种01串. Input 包含多组数据,每组数据占一行, ...
- 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串
1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...
- 最长相同01数的子串(map搞搞)--牛客第三场 -- Crazy Binary String
题意: 如题. 或者用我的数组分治也可以,就是有点愚蠢. //#include <bits/stdc++.h> #include <map> #include <iost ...
- poj3294 出现次数大于n/2 的公共子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 13063 Accepted: 3670 Descr ...
随机推荐
- Eclipse常见设置及快捷键使用总结(更新中)
Eclipse中常见设置: 1.Eclipse在保存时设置自动去掉多余的import和格式化代码 路径: window --> preferences --> java --> Ed ...
- JSTL、EL、ONGL、Struts标签的区别与使用
一.JSTL 来源 我们使用JSP开发信息展现非常方便,也可嵌入java代码用来实现相关逻辑,但同样带来了很多问题: jsp维护难度增加 出事提示不明确,不容易提示 分工不明确等 解决上面的问题可以 ...
- [POJ2398]Toy Storage(计算几何,二分,判断点在线段的哪一侧)
题目链接:http://poj.org/problem?id=2398 思路RT,和POJ2318一样,就是需要排序,输出也不一样.手工画一下就明白了.注意叉乘的时候a×b是判断a在b的顺时针还是逆时 ...
- AWS Python SDK boto3中的基本概念与使用方法
最近在用boto3编写AWS的lamda函数,学习到了boto3中的一些基本概念与使用方法.在此进行总结. 1. boto3提供了两个级别的接口来访问AWS服务:High Level的Resource ...
- poj 3792 Area of Polycubes (简单模拟)
题目 题意:在三维坐标系中,给定n个立方体的中心坐标,立方体的边长为1,按照输入顺序,后来输入的必须和之前输入的立方体有公共的边. 而且,不能和之前输入的立方体相同. 如果满足条件,输出表面积.如果不 ...
- Android中LayoutInflater的使用
Inflater英文意思是膨胀,在Android中应该是扩展的意思吧. LayoutInflater 的作用类似于 findViewById(),不同点是LayoutInflater是用来找layou ...
- ScaleGestureDetector缩放view
public class ScaleGesture implements OnScaleGestureListener { private float beforeFactor; private fl ...
- 利用dns解析来实现网站的负载均衡
当网站的访问量大了就会考虑负载均衡,这也是每一个架构师的基本功了,其基本地位就相当于相声里的说学逗唱,活好不好就看这个了 :) 传统的负载均衡思路是单点的,不管你是硬件的还是软件的基本都是这样的原理 ...
- WIN7开无线
可以的,WIN7自身就带有这个功能的,不过默认是不开启的,也可以下载一个软件来弄.1.请却仍您使用的操作系统是微软的Windows 7或者Windows server 2008 R2,正版盗版皆可.( ...
- MetadataType的使用,MVC的Model层数据验证
MetadataType的使用,MVC的Model层数据验证 指定要与数据模型类关联的元数据类 using System.ComponentModel.DataAnnotations; //指定要 ...