最大子序列問題的求解


問題#

最大子序列問題

方案一#

思路##

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

代碼##

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);
    }

結(jié)果##

執(zhí)行結(jié)果

分析##

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


方案二#

思路##查詢

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

代碼##

    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);
    }

分析##

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


方案三#

思路##

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

代碼##

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);
    }

分析##

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容