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

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

题目描述

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

思路分析

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

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

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

输入示例

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

推导验证

初始化

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

遍历数组并更新 mnmx

遍历到 -1
  • mn 更新为 Math.min(3, -1),因为 -1 比 3 小,所以 mn = -1。
  • mx 更新为 Math.max(3, -1),因为 -1 比 3 小,但是乘以 -1 可能会得到一个更大的正数,所以 mx = 3。
遍历到 -5
  • mn 更新为 Math.min(-1, -5, -1 * -5, 3 * -5),-1 * -5 = 5 和 3 * -5 = -15,所以 mn = -15。
  • mx 更新为 Math.max(3, -1, -1 * -5, 3 * -5),-1 * -5 = 5 和 3 * -5 = -15,所以 mx = 5。
遍历到 2
  • mn 更新为 Math.min(-15, 2, -15 * 2, 5 * 2),-15 * 2 = -30 和 5 * 2 = 10,所以 mn = -30。
  • mx 更新为 Math.max(5, -1, -15 * 2, 5 * 2),-15 * 2 = -30 和 5 * 2 = 10,所以 mx = 10。
遍历到 5
  • mn 更新为 Math.min(-30, 5, -30 * 5, 10 * 5),-30 * 5 = -150 和 10 * 5 = 50,所以 mn = -150。
  • mx 更新为 Math.max(10, -1, -30 * 5, 10 * 5),-30 * 5 = -150 和 10 * 5 = 50,所以 mx = 50。
遍历到 -9
  • mn 更新为 Math.min(-150, -9, -150 * -9, 50 * -9),-150 * -9 = 1350 和 50 * -9 = -450,所以 mn = -450。
  • mx 更新为 Math.max(50, -1, -150 * -9, 50 * -9),-150 * -9 = 1350 和 50 * -9 = -450,所以 mx = 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; // 返回最大乘积
    }
}

你可能感兴趣的:(算法,leetcode,动态规划,算法,数据结构,java)