【每日一题】LeetCode 2708.一个小组的最大实力值(一次遍历、分类讨论、动态规划)

【每日一题】LeetCode 2708.最大实力值小组(一次遍历、分类讨论、动态规划)

题目描述

给定一个整数数组 nums,表示一个班级中所有学生在一次考试中的成绩。老师想从这个班级中选出一部分同学组成一个非空小组,使得这个小组的实力值最大。小组的实力值定义为小组中所有学生成绩的乘积。请返回老师创建的小组能得到的最大实力值。

思路分析

这个问题可以通过动态规划的思想来解决。我们需要维护两个变量,mnmx,分别表示当前遍历到的元素之前可能的最小乘积和最大乘积。对于数组中的每个元素,我们考虑两种情况:不包括当前元素和包括当前元素。对于每种情况,我们分别更新 mnmx

  1. 不包括当前元素mnmx 保持不变。
  2. 包括当前元素:我们需要考虑当前元素与之前最小乘积和最大乘积相乘的情况。

由于数组中可能包含负数,我们需要特别注意负数的乘积可能会变成正数,这可能会影响最终的最大乘积。

输入示例

输入: nums = [3, -1, -5, 2, 5, -9]
输出: 1350

推导验证

初始化

  • mn = 3(数组的第一个元素)
  • mx = 3(同上)

遍历数组并更新 mnmx

遍历到 -1
  • x = -1
  • tmpe = mn = 3(保存当前 mn 的值,用于更新 mx

更新 mn

  • 不选 -1mn 不变,仍然是 3
  • -1,新的 mn-1
  • mn * x = 3 * (-1) = -3
  • mx * x = 3 * (-1) = -3
  • 新的 mnMath.min(3, -1, -3, -3) = -3

更新 mx

  • 不选 -1mx 不变,仍然是 3
  • -1,新的 mx-1
  • tmpe * x = 3 * (-1) = -3
  • mx * x = 3 * (-1) = -3
  • 新的 mxMath.max(3, -1, -3, -3) = 3
遍历到 -5
  • x = -5
  • tmpe = mn = -3(保存当前 mn 的值,用于更新 mx

更新 mn

  • 不选 -5mn 不变,仍然是 -3
  • -5,新的 mn-5
  • mn * x = -3 * (-5) = 15
  • mx * x = 3 * (-5) = -15
  • 新的 mnMath.min(-3, -5, 15, -15) = -5

更新 mx

  • 不选 -5mx 不变,仍然是 3
  • -5,新的 mx-5
  • tmpe * x = -3 * (-5) = 15
  • mx * x = 3 * (-5) = -15
  • 新的 mxMath.max(3, -5, 15, -15) = 15
遍历到 2
  • x = 2
  • tmpe = mn = -5(保存当前 mn 的值,用于更新 mx

更新 mn

  • 不选 2mn 不变,仍然是 -5
  • 2,新的 mn2
  • mn * x = -5 * 2 = -10
  • mx * x = 15 * 2 = 30
  • 新的 mnMath.min(-5, 2, -10, 30) = -5

更新 mx

  • 不选 2mx 不变,仍然是 15
  • 2,新的 mx2
  • tmpe * x = -5 * 2 = -10
  • mx * x = 15 * 2 = 30
  • 新的 mxMath.max(15, 2, -10, 30) = 30
遍历到 5
  • x = 5
  • tmpe = mn = -5(保存当前 mn 的值,用于更新 mx

更新 mn

  • 不选 5mn 不变,仍然是 -5
  • 5,新的 mn5
  • mn * x = -5 * 5 = -25
  • mx * x = 30 * 5 = 150
  • 新的 mnMath.min(-5, 5, -25, 150) = -5

更新 mx

  • 不选 5mx 不变,仍然是 30
  • 5,新的 mx5
  • tmpe * x = -5 * 5 = -25
  • mx * x = 30 * 5 = 150
  • 新的 mxMath.max(30, 5, -25, 150) = 150
遍历到 -9
  • x = -9
  • tmpe = mn = -5(保存当前 mn 的值,用于更新 mx

更新 mn

  • 不选 -9mn 不变,仍然是 -5
  • -9,新的 mn-9
  • mn * x = -5 * (-9) = 45
  • mx * x = 150 * (-9) = -1350
  • 新的 mnMath.min(-5, -9, 45, -1350) = -9

更新 mx

  • 不选 -9mx 不变,仍然是 150
  • -9,新的 mx-9
  • tmpe * x = -5 * (-9) = 45
  • mx * x = 150 * (-9) = -1350
  • 新的 mxMath.max(150, -9, 45, -1350) = 1350

结果

最终,mx 的值为 1350,这是所有可能子集中的最大乘积。

通过这个详细的步骤,我们可以看到每次迭代是如何考虑当前元素 x 是否加入到子集中,以及如何影响最小乘积 mn 和最大乘积 mx 的。这种方法确保了我们可以找到最大的乘积,而不需要枚举所有可能的子集。

代码实现

class Solution {
    public long maxStrength(int[] nums) {
        long mn = nums[0]; // 初始化最小乘积为数组的第一个元素
        long mx = mn;      // 初始化最大乘积也为数组的第一个元素
        for (int i = 1; i < nums.length; i++) {
            long x = nums[i]; // 当前遍历到的元素
            long oldMn = mn;  // 保存当前的最小乘积,以便在更新时使用
            long oldMx = mx;  // 保存当前的最大乘积,以便在更新时使用

            // 更新最小乘积
            // 考虑不包括当前元素和包括当前元素的情况
            mn = Math.min(Math.min(mn, x), Math.min(oldMn * x, oldMx * x));
            // 更新最大乘积
            // 考虑不包括当前元素和包括当前元素的情况
            mx = Math.max(Math.max(mx, x), Math.max(oldMn * x, oldMx * x));
        }
        return mx; // 返回最大乘积
    }
}
  • 20
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值