欢迎关注我的新博客点击打开链接
PAT1007:给定一个整数串,找出连续子串中合最大的子串。
《编程珠玑》中用专门的一章对这个问题进行了讲解。(《编程珠玑(第2版)》P73 第8章 算法设计技术)
第一次在PAT上遇到这个题目时,我的思路如下:
最简单的淡然是一个三层循环咯,O(n3),肯定会超时。节省时间的话,用动态规划吧。但简单的动态规划,显然是会超出内存限制的。有没有更巧妙的子问题划分方法呢?先找到子问题:因为要求的串必须连续,分治的时候需要考虑如何延续这个连续性,那么每个子问题中就得考虑找出三个串:1.即左端连续的最大串,2.右端连续的最大串,3.整个串中的最大串.由于每个问题都有三个量要维护,难道我得造出三个表来?卡主:(
《编程珠玑》列出了性能上依次递进的四个算法。这里我结合个人理解和感悟做一些阐释。
maxsofar = 0 for i = 0 [0, n) for j = [i, n) sum = 0; for k = [i, j] sum += x[k] /*sum is sum of x[i..j]*/ maxsofar = max(maxsofar, sum)
maxsofar = 0; for i = [0, n) sum = 0; for j = [i, n) sum += x[j] /* sum is sum of x[i..j]*/ max sofar = max(maxsofar, sum)
相比之下,动态规划的策略也是有memoization的思想在的,不过,在这里用DP将会创建一张很大的表。。。超出内存限定。
float maxsum3(l, u) if (l > u) /* zero elements*/ return 0 if (l == u) /* one element*/ return max (0, x[l]); m = (1 + u) / 2 /* find max crossing to left */ lmax = sum = 0 for (i = m; i >= 1; i--) sum += x[i] lmax = max(lmax, sum) /* find max croosing to right */ rmax = sum = 0; for i = (m, u] sum += x[i] rmax = max(rmax, sum) return max(lmax+rmax, maxsum3(l, m), maxsum3(m+1, u))
maxsofa = 0 maxendingright = 0 for i = [0, n) /* invariant: maxendingright and maxsofar are accurate for x[0..i-1]*/ maxendingright = max(maxendingright + x[i], 0) maxsofar = max(maxsofar, maxendingright)
根据这个思路,写出代码,一遍AC:)
总结: