動的計画法シリーズの「最大サブシーケンス合計」

53.最大サブオーダー合計

整数配列が与えられた場合nums、合計が最大の連続サブ配列を見つけ(サブ配列には少なくとも1つの要素が含まれます)、最大の合計を返します。

配列には複素数が含まれているため、この問題はスライディングウィンドウでは実行できず、ウィンドウのサイズを決定できません。

スライディングウィンドウは、合計がSである連続した正の数のシーケンスで使用されます

公式の問題説明にそのアイデアが見られますが、説明は非常に明確なので、ここでは繰り返しません... labuladongを
参照することもできます

方法1:動的計画法

class Solution {
    
    
    public int maxSubArray(int[] nums) {
    
    
        int tmp = 0;  // tmp 表示以nums[i]为结尾时的最大子序和,我们的目的是求得所有的,然后找出最大的
        int res = nums[0];  // res表示到目前nums[i]为止,之前以 nums[k],0≤k≤i 为结尾的所有最大子序和的最大值。
        for(int each : nums){
    
    
            tmp = Math.max(tmp + each, each);
            res = Math.max(res, tmp);
        }
        return res;
    }
}

時間計算量:O(n)

スペースの複雑さ:O(1)

方法2:分割統治

class Solution {
    
    
    public class Status {
    
    
        public int lSum, rSum, mSum, iSum;

        public Status(int lSum, int rSum, int mSum, int iSum) {
    
    
            this.lSum = lSum;
            this.rSum = rSum;
            this.mSum = mSum;
            this.iSum = iSum;
        }
    }

    public int maxSubArray(int[] nums) {
    
    
        return getInfo(nums, 0, nums.length - 1).mSum;
    }

    public Status getInfo(int[] a, int l, int r) {
    
    
        if (l == r) {
    
    
            return new Status(a[l], a[l], a[l], a[l]);
        }
        int m = (l + r) >> 1;
        Status lSub = getInfo(a, l, m);
        Status rSub = getInfo(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    public Status pushUp(Status l, Status r) {
    
    
        int iSum = l.iSum + r.iSum;
        int lSum = Math.max(l.lSum, l.iSum + r.lSum);
        int rSum = Math.max(r.rSum, r.iSum + l.rSum);
        int mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
        return new Status(lSum, rSum, mSum, iSum);
    }
}

時間計算量:時間計算量はO(n)です。
空間計算量:再帰はO(logn)スタック空間を使用するため、プログレッシブ空間計算量はO(logn)です。

「方法1」と比較すると、「方法2」は同じ時間計算量ですが、再帰を使用し、4つの情報の構造を維持するため、実行に少し時間がかかり、スペースの複雑さは方法1ほど良くありません。理解するのは難しいです。では、この方法の重要性は何ですか?

この質問については、それは本当です。しかし、間隔を解くだけでなく[0, n - 1][0,n−1]、サブインターバルの[l, r][l,r]問題を解くために、よく見る「方法II」を使用することもできます。我々は場合は[0, n - 1][0,n−1]、パーティションのすべての情報サブ間隔がダウンウェイ・ダウンのヒープ記憶メモリに登場された後、それは本当のツリーを構築するためには、我々はOで任意の間隔(LOGN)時間内に答えを求めることができます、シーケンス内の値を変更し、簡単なメンテナンスを行うこともできます。それでも、O(logn)時間の任意の間隔で答えを見つけることができます。大規模なクエリの場合、この方法の利点が反映されます。このツリーは、上記の魔法のデータ構造である線分ツリーです。

おすすめ

転載: blog.csdn.net/weixin_44471490/article/details/109189317