最大子序列問題的求解


問題#

最大子序列問題

方案一#

思路##

先搜尋出所有的子序列,然后求和比較

代碼##

public static void maxSubSum1(int[] a) {
        int maxSum = 0;
        int startIndex = 0;
        int endIndex = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = i; j < a.length; j++) {
                int tempSum = 0;

                for (int k = i; k <= j; k++) {
                    tempSum += a[k];
                }

                if (maxSum < tempSum) {
                    maxSum = tempSum;
                    startIndex = i;
                    endIndex = j;
                }
            }
        }
        System.out.println("this subsequence is from " + startIndex + " to " + endIndex + ", max sum is " + maxSum);
    }

結果##

執行結果

分析##

此方案用了三層循環,第一層循環確定子序列的起始位子(i),第二層循環確定子序列的終止位子(j)。通過第一層循環和第二層循環確定所有的子序列,然后再通過第三層循環求和。最后比較子序列的和,確定起始位子和終止位子。
此方案的時間復雜度為O(N^3 ),這完全取決于第三層for循環。所以為了提高效率,我們可以撤除第三層for循環(當然不是所有的三層循環都能這么做)。


方案二#

思路##查詢

搜索出所有的子序列,然后求和比較。(相對于方案一,去除了第三層求和的for循環)

代碼##

    public static void maxSubSum2(int[] a) {
        int maxSum = 0;
        int startIndex = 0;
        int endIndex = 0;
        for (int i = 0; i < a.length; i++) {
            int tempSum = 0;
            for (int j = i; j < a.length; j++) {
                tempSum += a[j];

                if (maxSum < tempSum) {
                    maxSum = tempSum;
                    startIndex = i;
                    endIndex = j;
                }
            }
        }
        System.out.println("this subsequence is from " + startIndex + " to " + endIndex + ", max sum is " + maxSum);
    }

分析##

此方案用了三層循環,第一層循環確定子序列的起始位子,第二層循環確定子序列的終止位子。通過第一層循環和第二層循環確定所有的子序列,然后通過第二層for循環求和。時間復雜度為O(N^2)。


方案三#

思路##

方案一和方案二的第一層循環用來確定子序列的起始位子,第二層循環用來確定子序列的結束位子。從兩層循環的起始位子看,都是從0開始,但是對于最大子序列,其起始位子的值不可能為負數;進一步看,如果最大子序列是AiAj,對于任意i<p<j,最大子序列的子序列AiAp的和一定大于0,所以對于任意從起始位子開始的子序列,若其和為負數,則丟棄,i繼續向前推進,直到數列遍歷完畢。

代碼##

public static void maxSubSum3(int a[]) {
        int maxSum = 0, thisSum = 0;
        for (int j = 0; j < a.length; j++) {
            thisSum += a[j];
            if (thisSum > maxSum) {
                maxSum = thisSum;
            } else if (thisSum < 0) {
                thisSum = 0;
            }
        }
        System.out.println(maxSum);
    }

分析##

此方法對于i(子序列的其實位子)進行了優化,因為我們關注的只是最大子序列,所以不必搜尋出所有的子序列(和方案一、方案二的區別),只需找到所有Ai~Ap(i<p<j)的和不為負數的子序列,然而這種方式只需要一層循環即可,所以去掉了最外層的循環。然后求出這些子序列的和,然后比較。此算法的時間復雜度為O(N)。
該算法的一個附加優點是,它對數據只進行一次掃描,一旦a[i]被讀入處理,就不需要被記憶。因此,如果數組在磁盤上或通過互聯網傳播,那么它就可以被按順序讀入,在內存中就不必存儲數組的任何部分。不僅如此,在任意時刻,算法都能對它已經讀入的數據給出子序列問題的正確答案。具有這種 特性的算法叫做聯機算法(on-line algrithm)。僅需要常量空間并以線性時間運行的聯機算法幾乎是完美的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,951評論 19 139
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,368評論 11 349
  • 旦旦早上六點多就醒了,天還沒太亮。 爸爸感冒了,我也感冒了,旦旦叫爸爸起床,爸爸每次都是哼哼,別說現在感冒了。 我...
    王莎莎2017閱讀 191評論 0 1
  • 在迷你公寓中出品精致美食,總能激發起對美好事物、愛和生活的共鳴。 今天給大家推薦一部BBC美食紀錄片《巴黎私廚》,...
    安廈閱讀 1,328評論 0 5
  • 【該自視容貌了】 魚尾紋爬上你的眼周,就證明你已經不再年輕了,哪怕你還只是20出頭,只有眼角有皺紋,也不會覺得你年...
    d956c705a280閱讀 315評論 1 0