1. 程式人生 > >最大子列和的四種演算法總結

最大子列和的四種演算法總結

最大子列和問題描述:

給定一串整數列中,求滿足子列和最大,並返回最大值。例如(2, -1, 6, 8, -5, 7, -11),其中的滿足和最大的子列為(2, -1, 6, 8, -5, 7),最大值為17。

演算法一

最蠢的方法是列舉法,把所有的子列都跑一遍。

int max_len(int a[], int N){
    int i, j, k, thisSum, maxSum = 0;
    for(i=0; i<N; i++){
        for(j=i; j<N; j++){
            thisSum = 0;
            for(k=i; k<=j; k++)
                thisSum += a[k];
            if
(thisSum > maxSum) maxSum = thisSum; } } return maxSum; }

複雜度為O(n^3),效率很低。

演算法二

演算法一中對j的迴圈是每次自加1,此時i是不變的,而k迴圈的作用是累加從ij的子列長度,可見雖然每次只需要再計算一個int值,但是k迴圈依然從最開始累加,沒有必要,所以k迴圈這裡可以優化。

int max_len(int a[], int N){
    int i, j, k, thisSum, maxSum = 0;
    for(i=0; i<N; i++){
        thisSum = 0
; for(j=i; j<N; j++){ thisSum += a[j]; //優化 if(thisSum > maxSum) maxSum = thisSum; } } return maxSum; }

也就是每次j移動的時候就判斷大小,複雜度為O(n^2)

演算法三

當演算法複雜度為O(n^2)時,我們總想通過分治法等方法將複雜度降為O(nlogn),但是這裡分治法需要注意的是,並不是所有子問題的解合併就是最後的解了,由於子列可能存在從左邊的子問題跨到右邊子問題的情況,如下圖:

這裡寫圖片描述

這時候在遞迴的同時還要加上一層從中間開始向兩邊延伸的判斷並賦值語句。

int max_len(int a[], int left, int right){
    int center, i, j, sum, left_sum, right_sum, s1, s2, lefts, rights;
    if(left == right){
        if(a[left] > 0)
            return a[left];
        else
            return 0;
    } else {
        center = (left + right) / 2;
        left_sum = max_len(a, left, center);
        right_sum = max_len(a, center + 1, right);
        s1 = 0;
        lefts = 0;
        for(i=center; i>=left; i--){
            lefts += a[i];
            if(lefts > s1) s1 = lefts;
        }
        s2 = 0;
        rights = 0;
        for(j=center+1; j<=right; j++){
            rights += a[j];
            if(rights > s2) s2 = rights;
        }
        if(s1+s2 < left_sum && right_sum<left_sum) return left_sum;
        if(s1+s2 < right_sum && left_sum < right_sum) return right_sum;
        return s1+s2;
    }
}

else中的兩個for迴圈是從中間開始,找出兩邊各自的最大值,然後相加,得出橫跨的最大值, 並與左右兩邊子問題的最大值進行比較。注意一定是從中間開始

該演算法的複雜度為O(nlogn)

演算法四

線上處理演算法:

int max_len(int a[], int N){
    int i, thisSum = 0, maxSum = 0;
    for(i=0; i<N; i++){
        thisSum += a[i];
        if(thisSum > maxSum)
            maxSum = thisSum;
        else if(thisSum < 0) //當前的子列和為負數,無論後面是什麼,負數與其相加肯定不能使子列和增大
            thisSum = 0;     //所以拋棄它,重新計算下一個子列和
    }
    return maxSum;
}

該演算法不容易理解,但是確是效率最高的,複雜度為O(n),因為至少要遍歷所有的元素,所以這已經是效率最高的演算法了。

相關推薦

大子求法

給定n(1<=n<=100000)個整數(可能為負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整數均為負數時定義子段和為0,依此定義,所求的最優值為: Max{0,a[i]+a

大子演算法總結

最大子列和問題描述: 給定一串整數列中,求滿足子列和最大,並返回最大值。例如(2, -1, 6, 8, -5, 7, -11),其中的滿足和最大的子列為(2, -1, 6, 8, -5, 7),最大值為17。 演算法一 最蠢的方法是列舉法,把所有的子列都跑

大子演算法比較

本文將會介紹最大子列和的四種不同複雜度演算法。 演算法一:暴力列舉法,演算法複雜度為O(N三次方) int maxsequence1(int A[], int N) { int ThisSum , MaxSum=0; int i, j,

數據結構(一)-----4方法求大子

include iss 需要 中間 () log 完整 font sso 數據結構(一)-----4種方法求最大子列和 1、暴力算法 /* 作者:mys 功能:求最大子列和 日期:2018/7/23 */ #include<stdio.h> #include&l

演算法學習——大子問題

參考視訊: 中國大學mooc——浙江大學——資料結構——陳越、何欽銘 問題描述: 求取陣列中最大連續子序列和,例如給定陣列為A={1, 3, -2, 4, -5}, 則最大連續子序列和為6,即1+3+(-2)+ 4 = 6。 演算法一 int MaxSubseqSu

大子問題3解法C語言

演算法1 找出所有的子列和,返回最大的 int MaxSubseqSum1(int str[],int n) //時間複雜度為O(n*2) { int maxsum=0; for(int i=0;i<n;i++){ int sum=0; for(int j=i;j

線上處理演算法 | HDU 1003 Max Sum 大子

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 299181    Accepted Submission(s)

PTA資料結構與演算法題目集(中文)5-1 大子問題 (20分)

給定KK個整陣列成的序列{ N_1N​1​​, N_2N​2​​, ..., N_KN​K​​ },“連續子列”被定義為{ N_iN​i​​, N_{i+1}N​i+1​​, ..., N_jN​j​​ },其中 1 \le i \le j \le K1≤i≤j≤

PTA 資料結構題目(1):大子問題(分而治之、線上處理演算法

題目來源: 問題描述: 問題分析: 對於一般的問題,原始解 都能通過一種 蠻力演算法,即窮舉法的思想得到。這題也不例外。 如果我們,把輸入的陣列,所有的子列都歷遍,並從中找出最大,即可得出我們的演算法。也就是版本一。 學習要點: 1、如何

演算法筆記-1-大子-Maximum Subsequence Sum

題目內容: Given a sequence of KK integers {N1,N2,...,NK}. A continuous subsequence is defined to be {Ni,Ni+1,...,Nj} where 1≤i≤j≤K1

短路的演算法總結

標題 ##最短路的四種演算法 1、floyd 核心程式碼只有五行 for(int k=1; k<=n; k++) for(int i=1; i<=n; i++) for(int j=1; j&

應用實例——大子問題

[] str else -s 給定 復雜 lin wid 工作流 題目描述:給定N個整數的序列{A1,A2,...,AN},求函數f(i,j)=max{0,ΣAk(i<=k<=j)}的最大值 算法1: 1 int MaxSubseqSum1(int A[],

大子(在線處理,復雜度O(n))

spa 最大子列和 pts 最大 int nts ups script 程序 #include<stdio.h> int main(){ int k,num,sum=0,Max=0; scanf("%d",&k); while(k--){ s

資料結構之大子

#include <stdlib.h> #include <stdio.h> int MaxSubseqSum(int a[],int N) {     int i,ThisSum = 0,MaxSum = 0;    &nb

PATtest1.3:大子

題目源於:https://pintia.cn/problem-sets/16/problems/663 題目要求:輸入一個數列,求其最大子列和。   問題反饋:1.部分C++程式碼不是很熟練               &

大子

int MaxSubSeqSum(int arr[], int n) { int currentSum, maxSum; currentSum = maxSum = 0; for(int i=0; i<n; i++) { curr

大子 – 線上處理

#最大子列和 – 線上處理 01-複雜度2 Maximum Subsequence Sum (25 分) The Maximum Subsequence is the continuous subsequence which has the largest sum of its elem

基礎數據結構應用——大子問題

pan nts -h 不同 ... printf fine () script 給定K個整數組成的序列{ N?1??, N?2??, ..., N?K?? },“連續子列”被定義為{ N?i??, N?i+1??, ..., N?j?? },其中 1。“最大子列和”則被定義

hdu1003Maxsum(大子問題)

這道題開始一直是Time Limit Exceeded,後來改動了又Wrong Answer,然後就是Presentation Error,改著改著終於AC了 題目連結:hdu1003 這是一道動態規劃的題目,即求最大子序列和:給定一列數a[1],a[2].....a[n],求a[i]+..

7-1 大子問題 (20 分)

給定K個整陣列成的序列{ N​1​​, N​2​​, …, N​K​​ },“連續子列”被定義為{ N​i​​, N​i+1​​, …, N​j​​ },其中 1≤i≤j≤K。“最大子列和”則被定義為所有連續子列元素的和中最大者。例如給定序列{ -2, 11,