最大子序列和(使用分治策略和递归)

例如对于输入:-2,11,-4,13,-5,-2答案为20 为方便起见 若所有整数为负数 则最大子序列和为0

算法一:

分治策略:其想法是把问题分成大致相等的子问题,然后递归的对他们求解,这是“分”的部分,,“治”是将两个子问题的解修不到一起并作少量附加工作,最后得到整个问题的解。

对于这个问题,可以分为三个部分,一个是最大子序列可能出现在输入数据的左半部分,第二种是出现在数据的右半部分,还有一种是在中间。第三部分可以通过求出前半部分的最大和(包括前半部分最后一个元素)和后半部分的最大和(包括后半部分的第一个元素),把这两个和相加就是中间部分的最大和,三个最大再比较下即可。

package com.itany.zuidazixulie;public class Test{ public static void main(String[] args) {int[] nums={2,-1,4,7,-6,5,8,-2};System.out.println("最大子序列和是:"+ maxSumRec(nums,0,nums.length-1)); } // 2 -1 4 7 | -6 9 8 -2 只对个数为2的N次方个数使用 public static int maxSumRec(int[] nums,int left,int right) {//基准情况 即只有一个数的情况if(left==right){if(nums[left]>0)return nums[left];elsereturn 0;}int center=left+(right-left)/2;int maxLeft=maxSumRec(nums,left,center);int maxRight=maxSumRec(nums,center+1,right);int maxLeftBorder=0,leftBorder=0;int maxRightBorder=0,rightBorder=0;for(int i=center;i>=left;i–){leftBorder+=nums[i];//此处必须包含边界 所以通过一直相加 如果>最大的和 则还有最大子序列if(leftBorder>maxLeftBorder)maxLeftBorder=leftBorder;}for(int i=center+1;i<=right;i++){rightBorder+=nums[i];//此处必须包含边界 所以通过一直相加 如果>最大的和 则还有最大子序列if(rightBorder>maxRightBorder)maxRightBorder=rightBorder;}return maxOfThree(maxLeft,maxRight,(maxLeftBorder+maxRightBorder)); } //计算三部分中的最大值 public static int maxOfThree(int maxLeft,int maxRight,int center) {int max=maxLeft;if(maxRight>max){max=maxRight;if(center>max)max=center;}return max; }}算法二:package com.itany.zuidazixulie;public class Test2{ public static void main(String[] args) {int[] nums={2,-1,4,7,-69,5,8,-2};System.out.println("最大子序列和是:"+ maxSumRec(nums)); } public static int maxSumRec(int[] nums) {int max=0;int thisSum=0;for(int i=0;i<nums.length;i++){thisSum+=nums[i];if(thisSum>max){max=thisSum;}//这时之前保存的最大子序列和仍然是存在的 分割 重新开始求和 再和之前的进行比较else if(thisSum<0){thisSum=0;}}return max; }}此算法是线性的 它只对数据进行一次扫描,不需要存储数组的其他部分,不仅如此,在任意时刻算法都能对已经读出的数据给出子序列问题的正确答案(其他算法不具有这个特性)。具有这种特性的算法叫做联机算法。仅需要常量空间并且以线性时间运行的联机算法几乎是完美的算法。

一只小狗在沙漠中旅行,找到了电线杆,结果还是憋死了,

最大子序列和(使用分治策略和递归)

相关文章:

你感兴趣的文章:

标签云: