1. 程式人生 > 資訊 >沒證:SpaceX 星鏈在印度收到政府命令,將向預購使用者退款

沒證:SpaceX 星鏈在印度收到政府命令,將向預購使用者退款

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

子陣列 是陣列中的一個連續部分。

示例 1:

輸入:nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出:6
解釋:連續子陣列[4,-1,2,1] 的和最大,為6 。

示例 2:

輸入:nums = [1]
輸出:1

示例 3:

輸入:nums = [5,4,-1,7,8]
輸出:23

提示:

1 <= nums.length <= 105
-104 <= nums[i] <= 104

進階:如果你已經實現複雜度為 O(n) 的解法,嘗試使用更為精妙的 分治法 求解。

解法一:動態規劃+貪心思想

首先要明白以下幾點:

  1. 設定dp[i]為第i位的暫存值(注意:不是最大值,只是下標滑到第i位時,dp的數值)
  2. 最大子序和的第一位一定為 正數
  3. 如果一個序列全為負數,那麼就要求負數的最大值(不要想當然的覺得最大數大於0!然後就隨隨便便的把dp[i]=0),
  4. 如果dp[i-1]<=0,那麼就要勇敢捨棄前面算的,從當前位重新開始(違反第2條)。
  5. 如果dp[i-1]>0,當然要加上當前位(貪心),至於加上當前位後是會減少dp[i]或者增加,留給下一個迴圈去判斷。

程式碼如下:

class Solution {
    public int maxSubArray(int[] nums) {

        int [] dp = new int [nums.length];
        dp[0] = nums[0];

        for(int i=1;i<nums.length;i++){
            if(dp[i-1]<=0){
                dp[i] = nums[i];
            }
            else{
                dp[i] = dp[i-1]+nums[i];
            }
        }
        java.util.Arrays.sort(dp);
        return dp[nums.length-1];
    }
}

上述程式碼並沒有清楚的寫出動態規劃的統一方程,但由for迴圈中的兩個if,

    if(dp[i-1]<=0){
        dp[i] = nums[i];
    }
    else{
        dp[i] = dp[i-1]+nums[i];
    }

可以推測dp公式:dp[i] = nums[i]+Math.max(dp[i-1], 0)

故上述程式碼可簡化為:

class Solution {
    public int maxSubArray(int[] nums) {

        int [] dp = new int [nums.length];
        dp[0] = nums[0];
        int max = dp[0];
        for(int i=1;i<nums.length;i++){
            dp[i] = nums[i] + Math.max(dp[i-1], 0);
            max = Math.max(dp[i], max);
        }
        return max;
    }
}

繼續優化

class Solution {
    public int maxSubArray(int[] nums) {
        int temp_i = nums[0];
        int max = nums[0];
        for(int i=1;i<nums.length;i++){
            temp_i = nums[i] + Math.max(temp_i, 0);
            max = Math.max(temp_i, max);
        } 
        return max;
    }
}