c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法
你好,我是goldsunC
让我们一起进步吧!
最大子序列和
Question
:给定整数(可能有负数),求的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为0)。
示例:
IN : [-2,11,-4,13,-5,-2]OUT : 20 即从A2-A4
暴力求解
第一种思路很简单,暴力求解。从数组第一个整数开始遍历每一种长度的最大值,然后遍历之后的最大值即是最大子序列和,如果最大值为负数则初始化为0,例如:指定数组为:[-2,11,-4,13,-5,-2]首先初始化最大值为-2,因为-2为负数所以最大值为0,然后计算-2+11,然后更新最大值为9,然后计算-2+11-4,保持当前最大值,然后计算-2+11-4+13,更新最大值为18,一直加到数组最后一位数,再从11开始求最大值,然后再从-4开始,就这样把数组每一种子序列和都遍历了,求得最大值。源码(Java):
public class maxValueSum { public static void main(String[] args) { int[] array = {-2,11,-4,13,-5,-2}; System.out.println(Max(array)); } public static int Max(int[] array) { int maxnum = array[0]; for (int i=0;i int currentnum = 0; for (int j=i;j currentnum += array[j]; if (currentnum>maxnum) maxnum = currentnum; } } return maxnum; }}
源码(Python):
def Max(array) : maxnum = 0 for i in range(len(array)): num = 0 for j in range(i,len(array)): num += array[j] if num > maxnum: maxnum = num return maxnumarray = [-2,11,-4,13,-5,-2]print(Max(array))
上面暴力求解法很简单,但是有个突出的问题,就是时间复杂度为O(),当涉及到大量输入的时候,效率非常低。
分治+递归求解
通常来讲,我们遇见递归的时候往往伴随的还有很高的时间复杂度,但对于这个问题来讲还有一个使用递归
+分治
实现的稍微复杂的方法,其时间复杂度却仅为O(),或许这个算法就是体现递归为例的最好范例了。这个算法使用一种"分治"
的策略,其想法是把问题分成两个大致相等的子问题,然后采用递归对他们求解,这是分
,治
是将两个子问题的解合并到一起并再做些少量的附加工作,最后得到整个问题的解。假如将传入的数组从中间分成左右两个部分,例如:[-2,11,-4,13,-5,-2]
->[-2,11,-4]
和[13,-5,-2]
那么问题的解可能出现在三处出现:
左半部分
[-2,-11,-4]
右半部分
[13,-5,-2]
或者横跨两个部分,它一定包括左半部分的最后一个值和右半部分的第一个值。
对上述问题求解得:左半部分的最大值为11
,右半部分的最大值为13
,而横跨这两个部分包含左半部分最后一个值以及右半部分第一个值的最大值为20
,即11-4+13,将三者对比,则返回最大值20。而这个时候我们求各部分最大值是直接看出来的,那实际应该怎么求呢?机器可看不出来,只能靠算法求解。那怎么求?用刚才讲过的暴力求解?那样的话我们分
这一次没有意义,因此我们需要递归地继续分
下去。看一下算法源码(Java):
public class maxVlaueSum2 { public static void main(String[] args) { // 初始化数组 int[] array = {-2,11,-4,13,-5,-2}; System.out.println(maxSum(array,0,array.length-1)); }
/** * 递归求解函数 * @param array :传入要解决的数组 * @param left :要解决子问题的左界 * @param right :要解决子问题的右界 * @return :返回三个部分的最大值 */ public static int maxSum(int[] array,int left,int right) { // BASE情况,如果递归到了最后一层,那么返回合适的值,小于0返回0,大于0返回该数。 if(left == right) { if (array[left] > 0) return array[left]; else return 0; } int center = (left+right)/2; // 取得数组中点 int leftSubSUM = maxSum(array,left,center); // 子问题左半部分最优解 int rightSubSUM = maxSum(array,center+1,right); // 子问题右半部分最优解
int leftNowSum = 0, maxleftSum = 0; // 当前问题左半部分等待求和的当前值以及最大值
// 遍历求包含左半部分最后一个值的最大值 for (int i=center;i>=left;i--) { leftNowSum += array[i]; if (leftNowSum > maxleftSum) { maxleftSum = leftNowSum; } } int rightNowSum = 0,maxrightSum = 0; // 当前问题右半部分等待求和的当前值以及最大值
// 遍历求包含右半部分的第一个值的最大值 for (int j=center+1;j<=right;j++) { rightNowSum += array[j]; if (rightNowSum>maxrightSum) { maxrightSum = rightNowSum; } } // 返回当前问题的左半部分最大值、右半部分的最大值和横跨两部分最大值的最大值。即为当前问题的解。 return Math.max(Math.max(leftSubSUM,rightSubSUM),(maxleftSum+maxrightSum)); }}
源码(Python):
def maxSUM(array,left,right): if left==right: if array[left] > 0: return array[left] else: return 0 center = int((left+right)/2) leftSubSUM = maxSUM(array,left,center) rightSubSUM = maxSUM(array,center+1,right)
leftNowNum,maxleftSum = 0,0 for i in reversed(range(left,center+1)): leftNowNum += array[i] if leftNowNum > maxleftSum: maxleftSum = leftNowNum
rightNowNum,maxrightSum = 0,0 for i in range(center+1,right+1): rightNowNum += array[i] if rightNowNum > maxrightSum: maxrightSum = rightNowNum return max(leftSubSUM,rightSubSUM,maxleftSum+maxrightSum)if __name__ == '__main__': array = [-2,11,-4,13,-5,-2] print(maxSUM(array,0,len(array)-1))
两个程序的原理相同,运行正确,不过鄙人水平有限,如果各位发现有问题还烦请指出,谢谢!这个算法稍微复杂一点,程序更长一点,不过时间复杂度只有O(),相比O()已经好了很多,不过事实上还有一种更加有效且巧妙的算法。
算法3
这个算法我也不清楚它的名字,不过它确是最好的,首先看源代码:源码(Java):
public class maxValueSum3 { public static void main(String[] args) { int[] array = {-2,11,-4,13,-5,-2}; System.out.println(maxSubSum(array)); } public static int maxSubSum(int [] array) { int maxSum = 0,NowSum = 0; for (int i = 0; i NowSum += array[i];
if (NowSum > maxSum) maxSum = NowSum; else if (NowSum 0) NowSum = 0; } return maxSum; }}
源码(Python):
def maxSubSum(array): maxSum,NowSum = 0,0 for i in range(len(array)): NowSum += array[i] if NowSum > maxSum: maxSum = NowSum elif NowSum 0: NowSum = 0 return maxSumif __name__ == '__main__': array = [-2,11,-4,13,-5,-2] print(maxSubSum(array))
代码很短,不过要想清楚原理可能比之前都稍微难点。它是正确可行的,并且不难看出时间复杂度为O(N),它的效率很高,不过到底是怎么实现的呢?那宁哥我就用蹩脚的话来简单分享下我的理解吧。首先可以看到,该算法只是简单遍历了一遍数组而已,就找到了最大子序列和。为什么可以这样?首先,任何负的子序列不可能是最优子序列的前缀。除非数组中的所有值均为负数,只要有一个正数,那么最优子序列的和的前缀一定不可能是负数。因此这也就说明了代码中的else if(NowSum<0) NowSUm=0;
了,也就是如果当前子序列的和为负值,那么初始化为0,它已经不可能是最有子序列的前缀了,就把它的记录抛弃了,如果当前位置在N,那问题就变成了求array[N+1]-array[array.length-1]的最有子序列了。然后还有一个判断语句if(NowSum > maxSum) maxSum = thisSum;
,看起来很简单,意思就是如果当前子序列和大于记录的最大值,那就更新。可如果放到整个程序里如何保证能正确运行呢?对一个子序列,如果是每一个数都递增或者递减比较好理解,递增的话最大子序列值就是从第一个大于0的数开始到整个序列,如果是递减的话就是第一个数开始到第一个小于等于0之前的那个数。还有两种情况,子序列整体递增或整体减小,但是数大大小小不确定。如果子序列整体是增加的,也好理解,仍然是整个序列值呗,那如果子序列是整体递减呢?如果整体是递减的,说明刚开始某个地方会有一个最大值,那样的话我们的方法在刚开始就已经把序列最大值记录了,后面只是更新而已,哈哈哈突然解决。明白了吗?
• end •
走在路上
goldsunC
c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法相关推荐
- 最大子序列求和_最大子序列和问题
问题描述: 给定一个整数序列,a0, a1, a2, -- , an(项可以为负数),求其中最大的子序列和.如果所有整数都是负数,那么最大子序列和为0: 例如:对于序列-2, 11, -4, 13, ...
- 最大子序列求和_连续子序列最大和与乘积问题的分析
问题描述 给定(可能是负的)整数序列A1, A2,...,AN, 寻找(并标识)使Sum(Ak)(k >=i, k <= j)的值最大的序列.如果所有的整数都是负的,那么连续子序列的最大和 ...
- 最大子序列求和_最大子序列和问题 一步一步到最优
在<数据结构和算法分析 C++描述>上看到了一个例子.看过之后,我就在想,这是怎么一步一步的递推出来的,想了好长时间,才整理成这篇博文. 问题描述: 给定一个整数序列,a0, a1, a2 ...
- 最长递增子序列 子串_最长递增子序列
最长递增子序列 子串 Description: 描述: This is one of the most popular dynamic programming problems often used ...
- 算法设计-递归法解最长公共子序列问题 C代码
给大家推荐一个公众号:诗葵1931 里面的诗歌很美 主要功能:递归法解最长公共子序列问题 #include<stdio.h> #include<string.h> /* 递归思 ...
- 两个字符串的最长公共子序列长度_【面试】动态规划-之最长公共子序列、最长公共子串问题...
先来说明下什么是最长公共子序列,什么是是最长公共子串,举一个实际例子,myblogs与belong,最长公共子序列为blog(myblogs, belong),最长公共子串为lo(myblogs, b ...
- c 最大子序列和_算法总结:左神class8—跳台阶+最长递增公共子序列
[跳台阶]有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法? public int s1(int n){ if (n< 1){ return 0; if(n == 1 || n ...
- c 最大子序列和_最大连续子序列
最大连续子序列:是指序列中所有子序列中元素和最大的一个 例如{-2,11,-4,13,-5.-2}中最大连续子序列为{11,-4,13}其和为20 若所有k个元素都为负数,则定义其最大和为0,输出整个 ...
- 最长递增子序列 子串_最长递增奇偶子序列
最长递增子序列 子串 Problem statement: 问题陈述: Given a sequence of numbers you have to find out the length of t ...
最新文章
- 网络虚拟化是否需要额外的网络架构?
- 双端队列【deque】的常见用法
- 车载电脑中控软件_ 车载手机支架怎么选?教你3招,开车的时候方便快捷
- 考研计算机专业复试,计算机专业考研复试准备
- python flask框架是什么_Flask框架是什么?带你安装运行第一个Flask程序
- 人工智能AI实战100讲(二)-自动驾驶传感器之激光雷达(三)主流车厂激光雷达的选择及布局
- (四)ElasticSearch之数据
- ajax预加载html seo,前端性能优化 — JS预加载和懒加载
- KDD Cup 2020多模态召回比赛亚军方案与搜索推荐业务的业务应用
- 第十五节:SpringBoot使用JPA访问数据库
- 网页几种保存类型与html文件格式,HTML 网页文件保存的格式为html或htm (5.0分)
- 一文吃透 VS Code+Git 操作(vs code中git的相关配置与使用)
- 我们为什么要结婚?(特别有道理)
- 房屋装修自装,如何自己做装修设计
- 前端开发面试问题及答案收录
- 16. 求两点之间的最短路径
- ios 事件穿透的原因和解决方法
- micropython 蓝牙音箱_Arduino从入门到创客带师(-1)—Hello World!
- “飞象”已露国家级工业互联网平台之像
- 免费的优质英文字体打包下载