找出满足差值条件的下标II-LeetCode
2905. 找出满足差值条件的下标II
🎯 问题描述
描述:
给你一个下标从 0 开始的整数数组 nums,另给你两个整数 indexDifference 和 valueDifference。
你的任务是找出两个下标 i 和 j,使得满足以下条件:
|i - j| >= indexDifference|nums[i] - nums[j]| >= valueDifference
如果存在多个满足条件的下标对,返回任意一个即可。如果不存在这样的下标对,返回 [-1, -1]。
说明:
-
这是一个数组遍历结合动态维护极值的问题。
-
核心策略:我们不需要双重循环去枚举所有
(i, j)对。 -
我们可以固定右边的下标
j,然后在左边合法的范围内(即i <= j - indexDifference)寻找最优的i。 -
为了使差值
|nums[i] - nums[j]|最大,i对应的值应该是左边范围内的最大值或最小值。 -
示例:
-
示例 1:
1 | 输入:nums = [5,1,4,1], indexDifference = 2, valueDifference = 4 |
💻 解题思路
思路1:单向遍历 + 动态维护极值
核心逻辑
- 遍历右端点
j:- 我们从
j = indexDifference开始遍历,因为i最小为 0,所以j至少要是indexDifference才能满足距离条件。
- 我们从
- 维护左端点
i的极值:- 对于当前的
j,合法的i的范围是[0, j - indexDifference]。 - 我们不需要每次都重新扫描这个范围。我们可以随着
j的增加,动态地将新的候选i(即j - indexDifference)加入到极值比较中。 - 维护两个变量:
min_idx(最小值的下标)和max_idx(最大值的下标)。
- 对于当前的
- 判断条件:
- 一旦我们有了当前合法范围内的最大值和最小值,我们只需要检查它们与
nums[j]的差值。 - 如果
nums[j] - nums[min_idx] >= valueDifference,说明找到了(小减大)。 - 如果
nums[max_idx] - nums[j] >= valueDifference,说明找到了(大减小)。 - 注意:题目要求绝对值差,所以这两种情况涵盖了所有可能。
- 一旦我们有了当前合法范围内的最大值和最小值,我们只需要检查它们与
代码实现
1 | class Solution: |
📊 性能分析
- 时间复杂度:
- 其中 是
nums的长度。 - 只需要遍历数组一次。
- 每次循环内的比较和赋值操作都是 。
- 其中 是
- 空间复杂度:
- 只使用了常数个变量 (
min_idx,max_idx,i,j)。
- 只使用了常数个变量 (
思考
-
为什么只需要维护一个
min_idx和max_idx?- 因为随着
j向右移动,合法的i的范围是单调扩大的(从[0, 0]到[0, 1],[0, 2]…)。 - 我们只需要把新进入范围的
nums[i]与当前的全局最值比较即可。 - 之前的最值依然有效,因为它们还在合法范围内。
- 因为随着
-
绝对值的处理:
- 题目要求
|nums[i] - nums[j]| >= valueDifference。 - 这等价于
nums[i] - nums[j] >= valueDifference或者nums[j] - nums[i] >= valueDifference。 - 为了让差值最大,
nums[i]应该取最大值或最小值。 - 所以只需要检查
nums[max_idx] - nums[j]和nums[j] - nums[min_idx]这两种情况。
- 题目要求
-
elif的使用:- 在更新极值时,代码使用了
elif。 - 这是安全的,因为一个数不可能同时小于最小值且大于最大值。
- 在更新极值时,代码使用了
-
边界情况:
indexDifference = 0:j从 0 开始,i可以是j。此时i和j可以重合。- 没有满足条件的对:循环结束后返回
[-1, -1]。 - 数组长度为 1:如果
indexDifference > 0,循环不会执行,返回[-1, -1]。
-
贪心策略:
- 我们一旦找到满足条件的对就立即返回。
- 题目只要求返回任意一个,所以不需要继续查找。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






