乘积最大子数组

题目解析

给定一个整数数组 nums,要求找到一个连续子数组,使其乘积最大,并返回该最大乘积。

算法思路

这个问题的关键在于:

1. 负数会改变乘积的大小,可能导致最大变最小,最小变最大。

2. nums[i] 可能是正数负数,每种情况的处理方式不同。

3. 需要跟踪两个变量:

• maxi:当前子数组的最大乘积

• mini:当前子数组的最小乘积(因为负数可能反转最小值为最大值)

状态转移方程:

如果 nums[i] 为正数

• maxi = max(nums[i], nums[i] * maxi)

• mini = min(nums[i], nums[i] * mini)

如果 nums[i] 为负数

• maxi 和 mini 互换后再计算:

• maxi = max(nums[i], nums[i] * mini)

• mini = min(nums[i], nums[i] * maxi)

最终 ans 记录全局最大乘积。

代码解析

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        int maxi = 1, mini = 1;  // 维护最大值和最小值
        int ans = INT_MIN;       // 记录全局最大乘积

        for (int i = 0; i < n; i++) {
            if (nums[i] < 0) {  // 负数翻转最大最小值
                swap(maxi, mini);
            }
            
            maxi = max(nums[i], nums[i] * maxi);  // 更新最大乘积
            mini = min(nums[i], nums[i] * mini);  // 更新最小乘积
            ans = max(ans, maxi);  // 更新全局最大乘积
        }

        return ans;
    }
};

详细运行步骤

假设 nums = [2, 3, -2, 4],我们来看代码如何执行。

初始化

maxi = 1, mini = 1, ans = INT_MIN

第 1 轮 (i=0, nums[i]=2)

nums[i] = 2
maxi = max(2, 2 * 1) = 2
mini = min(2, 2 * 1) = 2
ans  = max(INT_MIN, 2) = 2

状态:

maxi = 2, mini = 2, ans = 2

第 2 轮 (i=1, nums[i]=3)

nums[i] = 3
maxi = max(3, 3 * 2) = 6
mini = min(3, 3 * 2) = 3
ans  = max(2, 6) = 6

状态:

maxi = 6, mini = 3, ans = 6

第 3 轮 (i=2, nums[i]=-2)

nums[i] = -2
负数翻转 maxi 和 mini:
swap(maxi, mini) → maxi = 3, mini = 6

maxi = max(-2, -2 * 6) = -2
mini = min(-2, -2 * 3) = -12
ans  = max(6, -2) = 6

状态:

maxi = -2, mini = -12, ans = 6

第 4 轮 (i=3, nums[i]=4)

nums[i] = 4
maxi = max(4, 4 * -2) = 4
mini = min(4, 4 * -12) = -48
ans  = max(6, 4) = 6

状态:

maxi = 4, mini = -48, ans = 6

最终结果

return ans = 6

复杂度分析

时间复杂度:O(n),遍历数组一次。

空间复杂度:O(1),只使用了 maxi、mini 和 ans 变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值