1. 程式人生 > 其它 >LeetCode-152. 乘積最大子陣列

LeetCode-152. 乘積最大子陣列

題目來源

152. 乘積最大子陣列

題目詳情

給你一個整數陣列 nums,請你找出陣列中乘積最大的連續子陣列(該子陣列中至少包含一個數字),並返回該子陣列所對應的乘積。

示例 1:

輸入: [2,3,-2,4]
輸出: 6
解釋:子陣列 [2,3] 有最大乘積 6。

示例 2:

輸入: [-2,0,-1]
輸出: 0
解釋:結果不能為 2, 因為 [-2,-1] 不是子陣列。

題解分析

解法一-動態規劃

  1. 這題其實是最大連續子陣列題目的變型,原來的題目是求解連續子陣列的最大和。但遺憾的是,這題和原來的題目還是有很大區別的。因為乘積時可能遇到負數,但是負數和負數相乘會導致正數的出現,這是加法和減法所沒有的特徵。
  2. 因此,也不能使用類似於最大連續子陣列和的狀態轉移方程(\(dp[i] = max(dp[i-1] + nums[i], nums[i]\),最大值為dp結果陣列中各元素的最大值),需要採用新的思路來求解乘積子陣列的最大值。
  3. 考慮到這裡有負數會影響狀態轉移,並且如果當前數為負數,則我們希望該數前面的乘積為負數,且越小越好;如果當前數為正數,則我們希望前面數的乘積為正,且越大越好。
  4. 我們可以定義兩個dp陣列,一個儲存最大乘積,一個儲存最小乘積,結果為最大乘積陣列各元素中的最大值。
class Solution {
    final int MINS = -0X3F3F3F3F;
    public int maxProduct(int[] nums) {
        if(nums == null || nums.length == 0){
            return 0;
        }
        int len = nums.length;
        int[] dpmax = Arrays.copyOf(nums, len);
        int[] dpmin = Arrays.copyOf(nums, len);
        for(int i=1; i<len; i++){
            dpmax[i] = Math.max(dpmax[i-1] * nums[i], Math.max(dpmin[i-1] * nums[i], nums[i]));
            dpmin[i] = Math.min(dpmax[i-1] * nums[i], Math.min(dpmin[i-1] * nums[i], nums[i]));
        }
        int maxs = MINS;
        for(int i=0; i<len; i++){
            maxs = Math.max(maxs, dpmax[i]);
        }
        return maxs;
    }
}
Either Excellent or Rusty