1. 程式人生 > 其它 >[LeetCode] #53 最大子序和

[LeetCode] #53 最大子序和

[LeetCode] #53 最大子序和

給定一個整數陣列 nums,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。

輸入:nums = [-2,1,-3,4,-1,2,1,-5,4]

輸出:6

解釋:連續子陣列[4,-1,2,1] 的和最大,為6 。

暴力解法:

比較以某個節點為開頭的所有子序列的大小

class Solution {
    public int maxSubArray(int[] nums) {
        int res = nums[0];
        for(int j = 0; j < nums.length; j++){
            int sum = 0;
            
for(int i = j; i < nums.length; i++){ sum += nums[i]; if(sum > res) res = sum; } } return res; } }

動態規劃演算法:

以子序列的結束節點為基準,每一個結束結點(num)都利用上一個結束節點找到的最大值,找當前的最大值。

class Solution {
    public int maxSubArray(int[] nums) {
        int
sum = 0, res = nums[0]; for (int num : nums) { sum = Math.max(sum + num, num); res = Math.max(res, sum); } return res; } }

貪心演算法:

當前“連續和”為負數的時候立刻放棄,從下一個元素重新計算“連續和”,因為負數加上下一個元素 “連續和”只會越來越小。

class Solution {
    public int maxSubArray(int[] nums) {
        
if(nums == null || nums.length == 0) return 0; int curSum = 0; int maxSum = Integer.MIN_VALUE; int len = nums.length; for(int i = 0; i < len; i++){ curSum += nums[i]; maxSum = Math.max(maxSum,curSum); if(curSum < 0){ curSum = 0; } } return maxSum; } }

分治演算法:

最大連續和有三種情況。

出現在左半部分。遞迴求解。

出現在右半部分。遞迴求解。

有左有右。求左邊向左的最大和,再求右邊向右的最大和,兩邊相加。

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

知識點:

Math.max() 方法用於返回兩個引數中的最大值。

double max(double arg1, double arg2)

float max(float arg1, float arg2)

int max(int arg1, int arg2)

long max(long arg1, long arg2)

總結:

動態規劃演算法給我們提供了一個新思路,以子序列的結束節點為基準;

貪心演算法則通過“排除法”不斷變化開始節點從而減少時間複雜度;

分治演算法是將一個大規模的問題分解為幾個規模較小的子問題。