演算法-最大連續子序列和

來源:互聯網
上載者:User

標籤:

 題目:給定(可能是負的)整數A1、A2、…、AN,求出並確定對應的序列的最大值。如果所有的整數都是負數,那麼最大連續子數列和就是0,只是求出最大值,不需要求出具體的序列,作為這個題目的變種有很多情況下給你一個確定的數列,具體求和,大同小異,共有四種解法,按照時間複雜度來解,object-c實現,解法如下:

窮舉法

這個應該是這個題目最容易想到的方式,通過迴圈遍曆出所有的序列組合,求出最大的序列的最大值,代碼如下:

-(NSInteger)maxSubsequenceSum:(NSArray *)data{        NSInteger maxSum=0;//最大子序列的和        for (NSInteger start=0; start<[data count]; start++) {                for (NSInteger end=start; end<[data count]; end++) {                        NSInteger currentSum=0;//當前子序列的和            //data[start]~data[end]子序列的和            for (NSInteger i=start; i<=end; i++) {                                currentSum+=[[data objectAtIndex:i] integerValue];                            }            //通過判斷給最大子序列的和賦值            if (maxSum<currentSum) {                maxSum=currentSum;            }        }    }    return maxSum;}

  這個演算法三個迴圈,假設數組的長度為n,第一層迴圈為n,第二層迴圈n-start,第三層end-start,可算出時間複雜度O(n*n*n)=O(N^3),時間複雜度是跟輸入長度的立方有關,如果數組過長會是一個災難~

窮舉精簡版

對data[start]~data[end]子序列求和,可以由上一次求和data[start]~data[end-1]的結果加上data[end]得到,不需要重頭開始計算,時間複雜度為O(N^2) 

-(NSInteger)maxSubsequenceSumSecond:(NSArray *)data{    NSInteger maxSum=0;//最大子序列的和    for (NSInteger start=0; start<[data count]; start++) {                NSInteger currentSum=0;//當前子序列的和                for (NSInteger end=start; end<[data count]; end++) {            //data[start]~data[end]子序列的和,通過end加入,不需要迴圈            currentSum+=[[data objectAtIndex:end] integerValue];                        if (maxSum<currentSum) {                maxSum=currentSum;            }        }    }    return maxSum;}
遞迴版

題目中最大子序列可能在三個地方出現,左半部,右半部,跨越輸入資料的中部而佔據左右兩部分。前兩種情況遞迴求解,第三種情況的最大和可以通過求出前半部分最大和(包含前半部分最後一個元素)以及後半部分最大和(包含後半部分的第一個元素)相加而得到。

-(NSInteger)maxSubsequenceSumThird:(NSArray *)data  leftIndex:(NSInteger)left rightIndex:(NSInteger)right{    if (left==right) {        if (data[left]>0) {            //空集也算是子序列,空集和為0,最大子序列和最小為0            return [data[left] integerValue];        }else{            return 0;        }    }        NSInteger center=(left+right)/2;    NSInteger maxLeftSum=[self maxSubsequenceSumThird:data leftIndex:left rightIndex:center];    NSInteger maxRightSum=[self maxSubsequenceSumThird:data leftIndex:center+1 rightIndex:right];        //左半部分中包含最右邊元素的子序列的最大和    NSInteger  maxLeftBorderSum=0,leftBorderSum=0;    for (NSInteger i=center; i>=left; i--) {        leftBorderSum+=[data[i] integerValue];        if (leftBorderSum>maxLeftBorderSum) {            maxLeftBorderSum=leftBorderSum;        }    }    //右半部分包含最左邊的值    NSInteger maxRightBorderSum=0,rightBorderSum=0;    for (NSInteger i=center+1;i<right;i++) {        rightBorderSum+=[data[i] integerValue];        if (rightBorderSum>maxRightBorderSum) {            maxRightBorderSum=rightBorderSum;        }    }    //跨越左右部分的最大序列和    NSInteger maxMiddleSum=maxLeftBorderSum+maxRightBorderSum;    //左部分,右部分,跨越左右的最大序列和的最大值    NSInteger result=maxLeftSum>maxRightSum?maxLeftSum:maxRightSum;    return result>maxMiddleSum?result:maxMiddleSum;}

如果left==right,那麼T(1)=1,兩層迴圈的時間的次數2/N,最後的時間複雜度T(N)=2T(N/2)+O(N),等價於2T(N/2)+N,T(N)=N*(K+1)(這個可以自己推導),T(N)=N*(k+1)=NlogN +N=O(N );

最簡版

一次遍曆,如果小於0,重新設定迴圈的位置,時間複雜度O(N):

-(NSInteger)maxSubsequenceSumFour:(NSArray *)data{    NSInteger maxSum=0,currentSum=0;    for (NSInteger index=0; index<[data count]; index++) {        currentSum+=[[data objectAtIndex:index] integerValue];        //判斷當前序列的和是否為正數        if (currentSum<0) {            currentSum=0;        }        else if(maxSum<currentSum) {            maxSum=currentSum;        }    }    return maxSum;}

還有一個極端的情況,如果都是負數,不想返回0,擷取最大的負整數即可:

-(NSInteger)maxSubsequenceSumSpecial:(NSArray *)data{        NSInteger maxSum=[[data objectAtIndex:0] integerValue],currentSum=0;        NSInteger maxNegative=[[data objectAtIndex:0] integerValue];        for (NSInteger index=0; index<[data count]; index++) {                currentSum+=[[data objectAtIndex:index] integerValue];        if (currentSum<0) {            currentSum=0;        }        else if(maxSum<currentSum) {            maxSum=currentSum;        }        if (maxNegative<[data[index] integerValue]) {            maxNegative=[data[index] integerValue];        }    }    return maxSum>maxNegative?maxSum:maxNegative;    }

調用如下:

    NSArray *dataSource=[[NSArray alloc]initWithObjects:@"10",@"-9",@"-3",@"8",@"-2", nil];    MaxSubsequence  *maxSubsequence=[[MaxSubsequence alloc]init];    NSInteger result=[maxSubsequence maxSubsequenceSum:dataSource];    NSLog(@"最大的連續子序列的和:%ld",(long)result);            NSInteger resultSecond=[maxSubsequence maxSubsequenceSumSecond:dataSource];    NSLog(@"第二種最大的連續子序列的和:%ld",(long)resultSecond);    NSInteger thirdResult=[maxSubsequence maxSubsequenceSumThird:dataSource leftIndex:0 rightIndex:dataSource.count-1];    NSLog(@"第三種最大的連續子序列的和:%ld",(long)thirdResult);        NSInteger fourResult=[maxSubsequence maxSubsequenceSumFour:dataSource];    NSLog(@"第四種最大的連續子序列的和:%ld",(long)fourResult);        NSInteger specialResult=[maxSubsequence maxSubsequenceSumSpecial:dataSource];    NSLog(@"第四種全是負數最大的連續子序列的和:%ld",(long)specialResult);

  結果是10,數組簡單定義下,重要是看過程~

演算法-最大連續子序列和

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.