存档

文章标签 ‘最大子数组和’

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

2012年6月27日 1 条评论

---

最近练手,整理了一个“最”系列的主题,这些题目有点绕,个别的还有别名(详见博文),混在一块比较乱,就索性放在一起做了个整理,区别的时候要注意子序列与子串的不同,前者不要求连续,后者要求连续;由于大部分跟DP有关,有的还可以渐进寻求多种解法,可以用来做不错的练手。

下面是这些问题的博文目录

==========================

=1=最长公共子序列(LCS)==

=2=最长公共子串==

=3=最长重复子串==

=4=最长不重复子串==

=5=最长回文子串==

=6=最长递增子序列(LIS)==

=7=最大子数组和(连续子数组最大和)==

==========================

总结:

  1. 问题分类
    • 前两个是关于两个字符串的问题、中间三个是关于单个字符串的问题,最后两个是数组相关的问题;不过不一定绝对,例如最长公共子序列也可以是数组问题;
    • 从解决方案看,12属于“二维”DP问题,因为是两个对象间的问题;467属于“一维”DP问题,是单个对象的问题;345又是后缀数组的典型应用。
  2. 为练手,对大多数问题,尽量逐步探索,整理了多种思路,例如在最长不重复子串问题中,我逐步优化,尝试了四种实现方法,并成功得到了时间为O(N),辅助空间为常数的方案,回头反思,发现其优化的思维得益于对最大子数组和以及LIS的整理与思考。
  3. 这些问题之间相互有很多相通的地方,例如,在最长不重复子串问题中,其DP思路与最长递增子序列有点类似,二者同属“一维”的问题,并且都需要记录当前元素“之前”的某些信息;而在DP优化过程中,最长不重复子串问题又与最大子数组和的优化同出一辙,这两个“一维”的DP问题都只使用O(1)的空间便可以记录子问题的最优解,这种“便捷”的方案并不是空穴来风,而是先通过“规规矩矩”的DP一步步探索,才发现这种“trick”的存在,很是有意思。

勘误:

  • 本系列文章所有代码出现 char xx  [256] 的地方改为 int xx [256] ,因为从逻辑上讲char xx[256] 是有可能出问题的。(感谢HFC

阅读全文...

最大子数组和(最大子序列和 | 连续子数组最大和)

2012年6月22日 16 条评论

--

一个有N个元素的整型数组arr,有正有负,数组中连续一个或多个元素组成一个子数组,这个数组当然有很多子数组,求子数组之和的最大值。例如:[0,-2,3,5,-1,2]应返回9,[-9,-2,-3,-5,-3]应返回-2。

网上有称之为最大子序列和,亦有称连续子数组最大和。个人觉得叫最大子序列和不太妥,数学上讲,子序列不一定要求连续,而这里我们的题目必然要求是连续的,如果不连续而求子序列最大和很显然就无意义了,这也是为啥又称连续子数组最大和。不过,莫要在意细节。

鉴于《编程之美》对其有几个扩展问题,这里就练手一并实现了,不过整理过程中发现了《编程之美》中的解法错误,查了一下官网的勘误表,居然木有,小激动了一下。。。本节包括以下内容:

==基本思路==

==DP方案==

==返回最大子数组始末位置==

==数组首尾相连【《编程之美》解法错误分析】==

==类似问题==

==================================

基本思路

最直接的方法就是找出所有的子数组,然后求其和,取最大。如果每个子数组都遍历求和,该方法的复杂度为O(N^3),仔细考虑,在遍历过程中,这些子数组的和是有重复计算的:下标i与j之间的区间和Sum[i,j]=Sum[i,j-1]+arr[j]。于是子数组和的求法不必每次都遍历,算法复杂度可以降为O(N^2)。代码如下:

阅读全文...