lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1. 题目

 

读题

https://leetcode.cn/problems/maximum-product-subarray/

 

 

考查点

 

2. 解法

思路

 

思路是这样的:我们要找到一个子数组,使得它的乘积最大。我们可以用动态规划的方法,定义一个状态dp[i],表示以第i个元素结尾的子数组的最大乘积。那么我们要求的就是dp[0]到dp[n-1]中的最大值,其中n是数组的长度。但是这样定义状态有一个问题,就是如果第i个元素是负数,那么它可能会把之前的最大乘积变成最小乘积,或者把之前的最小乘积变成最大乘积。所以我们需要同时维护两个状态,一个是max[i],表示以第i个元素结尾的子数组的最大乘积,另一个是min[i],表示以第i个元素结尾的子数组的最小乘积。那么我们要求的就是max[0]到max[n-1]中的最大值。那么如何更新这两个状态呢?我们可以根据第i个元素的正负号来分情况讨论:

  • 如果第i个元素是正数,那么它会使得之前的最大乘积变得更大,也会使得之前的最小乘积变得更小。所以我们有:
    • max[i] = max(nums[i], max[i-1] * nums[i])
    • min[i] = min(nums[i], min[i-1] * nums[i])
  • 如果第i个元素是负数,那么它会使得之前的最大乘积变成最小乘积,也会使得之前的最小乘积变成最大乘积。所以我们有:
    • max[i] = max(nums[i], min[i-1] * nums[i])
    • min[i] = min(nums[i], max[i-1] * nums[i])
  • 如果第i个元素是0,那么它会使得之前的任何乘积都变成0。所以我们有:
    • max[i] = 0
    • min[i] = 0

由于每个状态只和前一个状态有关,所以我们可以用两个变量来代替数组,节省空间。另外,由于负数会导致最大和最小乘积交换,所以我们在更新之前要先判断当前元素的正负号,并且如果是负数就交换两个变量的值。

代码逻辑

 

  • 步骤一:判断数组是否为空或者长度为0,如果是,就返回0,因为没有子数组。
  • 步骤二:初始化两个变量max和min,分别表示以第一个元素结尾的子数组的最大乘积和最小乘积,也就是第一个元素本身。同时,初始化一个全局变量result,表示最终要返回的最大乘积,也就是max的初始值。
  • 步骤三:从第二个元素开始遍历数组,对于每个元素,执行以下的子步骤:
    • 子步骤一:判断当前元素的正负号,如果是负数,就交换max和min的值,因为负数会导致最大和最小乘积反转。
    • 子步骤二:更新max和min的值,根据之前的思路,用当前元素和当前元素乘以之前的max或min来比较,取较大或较小的值作为新的max或min。
    • 子步骤三:更新result的值,用当前的max和之前的result来比较,取较大的值作为新的result。
  • 步骤四:遍历结束后,返回result作为答案。

具体实现

class Solution {
    public int maxProduct(int[] nums) {
        // edge case
        if (nums == null || nums.length == 0) return 0;
        // initialize two variables to store the max and min product ending with current element
        int max = nums[0];
        int min = nums[0];
        // initialize a global variable to store the max product
        int result = max;
        // loop through the array
        for (int i = 1; i < nums.length; i++) {
            // if current element is negative, swap max and min
            if (nums[i] < 0) {
                int temp = max;
                max = min;
                min = temp;
            }
            // update max and min
            max = Math.max(nums[i], max * nums[i]);
            min = Math.min(nums[i], min * nums[i]);
            // update result
            result = Math.max(result, max);
        }
        return result;
    }
}

  

3. 总结

posted on 2023-05-01 16:46  白露~  阅读(8)  评论(0编辑  收藏  举报