找出数组中的所有 K 近邻下标 -LeetCode
2200. 找出数组中的所有 K 近邻下标
🎯 问题描述(来源于LeetCode)
描述:
给你一个下标从 0 开始的整数数组 nums 和两个整数 key 和 k。
K 近邻下标 定义为 nums 中某个下标 i,满足至少存在一个下标 j 使得 |i - j| <= k 且 nums[j] == key。
以列表形式返回所有 K 近邻下标,按 递增顺序 排序。
说明:
- 一个下标可能对应多个
key位置,但只计入一次。
示例:
- 示例 1:
1 | 输入: nums = [3,4,9,1,3,3], key = 3, k = 2 |
- 示例 2:
1 | 输入: nums = [1,2,3,4,5], key = 2, k = 1 |
💻 解题思路
思路:快慢指针扫描(一次遍历,线性时间)
- 快指针
fast:遍历数组,寻找值为key的位置。 - 慢指针
slow:始终指向下一个尚未被检查的下标,初始为 0。
当fast指向key时,从slow和fast - k的较大值开始,依次检查所有满足|slow - fast| <= k的下标,并将它们加入结果列表,同时slow递增。
由于slow永不回退,且只向前移动,每个下标最多被访问一次,保证了线性时间复杂度。
算法步骤
- 初始化
slow = 0,结果列表ans = [],数组长度l。 - 遍历
fast从 0 到l-1:- 若
nums[fast] == key:- 将
slow更新为max(slow, fast - k),确保不会遗漏之前未扫描的下标。 - 当
slow <= fast + k且slow < l时:- 由于已经保证
slow >= fast - k,此时一定有abs(slow - fast) <= k,直接将slow加入ans。 slow += 1。
- 由于已经保证
- 将
- 继续下一个
fast。
- 若
- 返回
ans(已自动升序且无重复)。
代码实现(您的优化代码)
1 | from typing import List |
📊 性能分析
- 时间复杂度:,每个下标最多被
slow访问一次,外层循环 。 - 空间复杂度:,用于存储结果列表。
思考
相比最初的版本,你通过维护 slow 指针不重置,并利用 max(slow, fast - k) 跳过已经处理过的下标,将算法从可能的 优化为严格的 。同时,由于 slow 递增,结果自动保持升序,无需额外排序或去重。这是本题非常优雅的线性解法。
关键点:
- 只有当
nums[fast] == key时才触发添加,但slow的推进不受key位置影响,确保覆盖所有可能的下标。 - 由于
slow始终指向下一个可能合法的下标,每个下标只被考虑一次,不会重复。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






