有序三元组中的最大值II-LeetCode
2874. 有序三元组中的最大值II
🎯 问题描述
描述:
给你一个下标从 0 开始的整数数组 nums。
请你找出并返回满足以下条件的三元组 的最大值:
- 三元组的值定义为:
如果所有三元组的值都小于 0,则返回 0。
说明:
-
这是一个枚举中间点结合前后缀极值预处理的问题。
-
核心策略:
- 我们要最大化 。
- 我们可以枚举中间的下标 。
- 当 固定时,为了使结果最大,我们需要:
- 在 的左侧()找到最大的 ,这样 才会尽可能大。
- 在 的右侧()找到最大的 ,这样乘积的结果才会尽可能大(假设差值为正)。
-
预处理:通过预处理后缀最大值数组,我们可以 获取右侧最大值;通过动态维护前缀最大值,我们可以 获取左侧最大值。
-
示例:
-
示例 1:
1 | 输入:nums = [12,6,1,2,7] |
💻 解题思路
思路1:后缀最大值 + 前缀动态维护
核心逻辑
- 预处理后缀最大值:
- 构建数组
suf,其中suf[i]表示nums[i...n-1]范围内的最大值。 - 这样,对于任意 ,其右侧最大的 就是
suf[j+1]。
- 构建数组
- 动态维护前缀最大值:
- 在遍历中间点 时,用变量
pre记录nums[0...j-1]范围内的最大值。
- 在遍历中间点 时,用变量
- 枚举中间点 :
- 遍历 从 到 。
- 计算当前三元组的值:
(pre - nums[j]) * suf[j+1]。 - 更新全局最大值
ans。 - 更新
pre,将nums[j]纳入左侧范围,供下一轮使用。
- 处理负数结果:
- 题目要求如果最大值小于 0 则返回 0。
代码实现
1 | class Solution: |
📊 性能分析
- 时间复杂度:
- 其中 是
nums的长度。 - 构建后缀数组需要一次遍历 。
- 枚举中间点 需要一次遍历 。
- 总时间复杂度为 。
- 其中 是
- 空间复杂度:
- 需要一个长度为 的数组
suf来存储后缀最大值。
- 需要一个长度为 的数组
思考
-
为什么只需要最大值?
- 我们要最大化 。
- 对于固定的 (),为了让结果最大:
- 如果 ,我们需要 尽可能大。
- 如果 ,我们需要 尽可能小(但这题里如果 是负数,且 是正数,结果就是负的,不如直接返回 0)。
- 题目数据范围通常暗示我们寻找正向的最大收益。即使考虑负数情况,通常也是找极值。在这里,贪心策略是找左侧最大值和右侧最大值。
-
后缀数组的构建:
suf[i] = max(suf[i+1], nums[i])。- 这保证了
suf[i]包含了从i到末尾的所有元素的最大值。 - 当我们检查 时,右侧的范围是 到 ,所以使用
suf[j+1]。
-
前缀变量的更新:
pre初始化为nums[0]。- 在每次循环结束时,
pre = max(pre, nums[j])。 - 这保证了当循环到 时,
pre存储的是nums[0...j]的最大值。
-
边界条件:
- 的范围是 到 。
- 因为 至少为 0, 至多为 ,所以 不能是第一个或最后一个元素。
-
结果处理:
- 初始化
ans为负无穷。 - 最后返回时判断
ans > 0,否则返回 0。
- 初始化
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






