Easy
题目描述
给你一个下标从 0 开始的整数数组 nums 和两个整数 key 和 k。K 近邻下标 是 nums 中的一个下标 i,并满足至少存在一个下标 j 使得 |i - j| <= k 且 nums[j] == key。
以列表形式返回按 递增顺序 排序的所有 K 近邻下标。
示例 1:
输入:nums = [3,4,9,1,3,9,5], key = 9, k = 1
输出:[1,2,3,4,5,6]
解释:这里,nums[2] == key 且 nums[5] == key 。
- 对于下标 0 ,|0 - 2| > k 且 |0 - 5| > k ,所以不存在 j 使得 |0 - j| <= k 且 nums[j] == key 。因此 0 不是一个 K 近邻下标。
- 对于下标 1 ,|1 - 2| <= k 且 nums[2] == key ,所以 1 是一个 K 近邻下标。
- 对于下标 2 ,|2 - 2| <= k 且 nums[2] == key ,所以 2 是一个 K 近邻下标。
- 对于下标 3 ,|3 - 2| <= k 且 nums[2] == key ,所以 3 是一个 K 近邻下标。
- 对于下标 4 ,|4 - 5| <= k 且 nums[5] == key ,所以 4 是一个 K 近邻下标。
- 对于下标 5 ,|5 - 5| <= k 且 nums[5] == key ,所以 5 是一个 K 近邻下标。
- 对于下标 6 ,|6 - 5| <= k 且 nums[5] == key ,所以 6 是一个 K 近邻下标。
因此,按递增顺序返回 [1,2,3,4,5,6] 。
示例 2:
输入:nums = [2,2,2,2,2], key = 2, k = 2
输出:[0,1,2,3,4]
解释:对于 nums 中的所有下标 i ,总存在某个下标 j 使得 |i - j| <= k 且 nums[j] == key ,所以每个下标都是一个 K 近邻下标。
因此,返回 [0,1,2,3,4] 。
提示:
1 <= nums.length <= 10001 <= nums[i] <= 1000key是数组nums中的一个整数1 <= k <= nums.length
解题思路
这道题要求找出数组中所有 K 近邻下标,即距离 key 值的位置不超过 k 的下标。
解法思路分析:
暴力法:对于每个下标 i,遍历整个数组寻找是否存在 j 使得
|i-j| <= k且nums[j] == key。时间复杂度 O(n²)。优化思路:先找出所有 key 的位置,然后对每个位置计算其影响范围
[pos-k, pos+k],将所有影响范围内的下标加入结果。最优解法:使用集合去重。首先遍历数组找到所有等于 key 的下标,然后对每个这样的下标,将其左右各 k 个位置(在数组范围内)的下标都加入集合中。最后将集合转换为有序列表返回。
推荐解法: 集合去重法,既简洁又高效,时间复杂度为 O(nk),在给定约束下表现良好。
核心步骤:
- 遍历数组,找到所有值为 key 的下标
- 对每个 key 的下标,计算其影响范围 [max(0, pos-k), min(n-1, pos+k)]
- 将影响范围内的所有下标加入集合
- 将集合转换为有序列表返回
代码实现
class Solution {
public:
vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {
int n = nums.size();
set<int> result_set;
// 找到所有等于key的位置
for (int i = 0; i < n; i++) {
if (nums[i] == key) {
// 对于每个key的位置,添加距离<=k的所有下标
int left = max(0, i - k);
int right = min(n - 1, i + k);
for (int j = left; j <= right; j++) {
result_set.insert(j);
}
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
class Solution:
def findKDistantIndices(self, nums: List[int], key: int, k: int) -> List[int]:
n = len(nums)
result_set = set()
# 找到所有等于key的位置
for i in range(n):
if nums[i] == key:
# 对于每个key的位置,添加距离<=k的所有下标
left = max(0, i - k)
right = min(n - 1, i + k)
for j in range(left, right + 1):
result_set.add(j)
return sorted(list(result_set))
public class Solution {
public IList<int> FindKDistantIndices(int[] nums, int key, int k) {
int n = nums.Length;
var resultSet = new HashSet<int>();
// 找到所有等于key的位置
for (int i = 0; i < n; i++) {
if (nums[i] == key) {
// 对于每个key的位置,添加距离<=k的所有下标
int left = Math.Max(0, i - k);
int right = Math.Min(n - 1, i + k);
for (int j = left; j <= right; j++) {
resultSet.Add(j);
}
}
}
var result = resultSet.ToList();
result.Sort();
return result;
}
}
var findKDistantIndices = function(nums, key, k) {
const n = nums.length;
const resultSet = new Set();
// 找到所有等于key的位置
for (let i = 0; i < n; i++) {
if (nums[i]
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(nk) | 最坏情况下所有元素都等于key,每个位置需要添加2k+1个下标 |
| 空间复杂度 | O(min(n, mk)) | m为key出现次数,结果集合最大为n,实际大小取决于重叠情况 |