java求連續子數組的和最大

          Posted on 2014-03-05 11:47 dongisland 閱讀(1712) 評論(0)  編輯  收藏

          題目描述:
          輸入一個整形數組,數組里有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。

          求所有子數組的和的最大值。要求時間復雜度為O(n)。

          思路:

          我們可以使用分治法或者減治法來處理這個問題。

          分治法    
          目標:把1個大問題分成2個小問題,2個小問題還可以再分,直到問題規模小的可以簡單解決。

          將該數組等分成兩個子數組,假如知道左右兩側兩個數組的各自的最大子數組和,那么整個數組的最大子數組和可能為三種情況:

          • 右側數組的最大子數組和
          • 左側數組的最大子數組和
          • 左右兩側數組中間毗鄰位置連接形成的子數組的和的最大值(如-6,4,-3,2####5,-6,9,-8,左側最大值為4,右側為9,中間毗鄰位置從2和5向兩側相加,得到中間毗鄰子數組4,-3,2,5,-6,9和為11,三者比較得最大子數組和為11)。

          遞歸到數組中只包含一個數字。

          這種思路也是可行的。進行ln(n)次拆分,每次拆分后進行n次比較,所以算法復雜度為n*ln(n)。但還達不到題目的要求。

          java代碼:

           1 package com.island.info;
           2 /**
           3  * <p>Title: TestMaxArray.java</p>
           4  * <p>Description: 分治法求解連續和最大</p>
           5  * @date 2014-3-05
           6  *
           7  */
           8  
           9 public class MaxSub {
          10         static int arr[] = {4,-3,5,-2,-1,2,6,-2};    //也可以隨機生成
          11         public static void main(String args[]){
          12             System.out.println(max(arr));
          13         }
          14  
          15         //包裝函數
          16         public static int max(final int[] arr){
          17             System.out.println("(1)*****arr.length-1----------------->:"+ (arr.length-1));
          18             return max(arr,0,arr.length-1);
          19         }
          20  
          21         //核心代碼:遞歸調用max()
          22         public static int max(final int[] arr,int leftIndex, int rightIndex){
          23             System.out.println("(2)*****leftIndex--------rightIndex--->:"+leftIndex+"|***************|"+rightIndex);
          24             int sum = 0,leftHalfMax = 0, rightHalfMax = 0;
          25             if (rightIndex-leftIndex==0){
          26                 return arr[rightIndex];
          27             } else {
          28                 int center = (leftIndex+rightIndex)/2;//2分查找中間節點
          29                 int maxLeft = max(arr,leftIndex,center);//左邊最大的
          30                 int maxRight = max(arr,center+1,rightIndex);//右邊最大的
          31                 //以下是查找跨越中間點的最大子序列
          32                 //從中點到左側:
          33                 for (int i=center;i>=leftIndex;--i){
          34                     sum+=arr[i];
          35                     if (sum>leftHalfMax){
          36                         leftHalfMax = sum;
          37                     }
          38                 }
          39                 System.out.println("左邊的sum----------->:"+sum);
          40                 sum=0;
          41                 //從中點到右側
          42                 for (int i=center+1;i<=rightIndex;++i){
          43                     sum+=arr[i];
          44                     if (sum>rightHalfMax){
          45                         rightHalfMax = sum;
          46                     }
          47                 }
          48                 System.out.println("右邊的sum----------->:"+sum);
          49                 return max(maxLeft,maxRight,leftHalfMax+rightHalfMax);
          50             }
          51         }
          52  
          53         //三者取最大值
          54         public static int max(int a,int b,int c){
          55             return a>b?(a>c?a:c):(b>c?b:c);
          56         }
          57     }

          減治法

          目標:將問題規模不斷減小,直到可以簡單處理為止。

          假設我們已知一個數組的最大子數組和,現在在該數組后面增加一個數字,新數組的最大子數組和可能是什么呢:

          • 原數組的最大子數組和;
          • 新增加的數字為正數,和最右側的子數組形成了一個新的最大子數組和(所以為了通過一次遍歷完成,我們需要保存最右側的子數組的最大和)。

          然后將兩個數字進行比較即可。

          所以減治至數組只包含最左側一個數字,我們知道它的最大子數組和和最右側子數組最大和都為還數字,逐次加1個數字直到整個數組即可。

          java代碼:

           1 package com.island.info;
           2  
           3 /**
           4  * <p>Title: TestMaxArray.java</p>
           5  * <p>Description: 分治法求解連續和最大</p>
           6  * @date 2014-3-05
           7  *
           8  */
           9 public class MaxSubArraySum {
          10  
          11     private static long getMax(long a, long b) {
          12         return a > b ? a : b;
          13     }
          14      
          15     /** 
          16     * 獲得連續子數組的最大和 
          17     * @param array 
          18     * @return 最大和,此處用了Long型是為了表示當參數為null或空時,可以返回null,返回其它任何數字都可能引起歧義。 
          19     */ 
          20  
          21     public static Long getMax(int[] array) {
          22          
          23         if (array == null || array.length <= 0) {
          24             return null;
          25         }
          26          
          27         long maxSum = array[0]; //所有子數組中最大的和 
          28         long righteEdge = array[0]; //右側子數組的最大和
          29         for (int i = 1; i < array.length; i++) {
          30             //當右側子數組的最大和為負數時,對于新數組,右側子數組的最大和為新增加的數。  
          31             if (righteEdge < 0) {
          32                 righteEdge = array[i];
          33             } else { //為正數時,對于新數組,右側子數組的最大和為新增加的數 + 原來的最大和。  
          34                 righteEdge += array[i];
          35             }
          36             //所有子數組中最大的和  
          37             System.out.println("righteEdge-------------maxSum:"+righteEdge+"****************"+maxSum);
          38             maxSum = getMax(righteEdge, maxSum);
          39         }
          40         return maxSum;
          41     }
          42  
          43     public static void main(String[] args) {
          44         int[] array = {1-2310-472-5};
          45         //int arr[] = {4,-3,5,-2,-1,2,6,-2};  
          46         System.out.println("Max sum: " + MaxSubArraySum.getMax(array));
          47     }
          48  
          49 }

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          posts - 5, comments - 0, trackbacks - 0, articles - 0

          Copyright © dongisland

          主站蜘蛛池模板: 乌什县| 九龙县| 宽甸| 武乡县| 东乌珠穆沁旗| 烟台市| 拉孜县| 黄龙县| 伽师县| 岫岩| 鲁山县| 枣阳市| 林甸县| 石屏县| 顺昌县| 庆城县| 长宁区| 诸城市| 久治县| 新巴尔虎左旗| 师宗县| 且末县| 清河县| 郴州市| 望城县| 三门峡市| 腾冲县| 砚山县| 连州市| 兴仁县| 通城县| 晋宁县| 怀化市| 祁东县| 商都县| 邢台县| 彰化市| 崇义县| 普兰店市| 汉阴县| 浙江省|