Easy

题目描述

给你一个下标从 0 开始的整数数组 nums 和两个整数 keykK 近邻下标nums 中的一个下标 i,并满足至少存在一个下标 j 使得 |i - j| <= knums[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 <= 1000
  • 1 <= nums[i] <= 1000
  • key 是数组 nums 中的一个整数
  • 1 <= k <= nums.length

解题思路

这道题要求找出数组中所有 K 近邻下标,即距离 key 值的位置不超过 k 的下标。

解法思路分析:

  1. 暴力法:对于每个下标 i,遍历整个数组寻找是否存在 j 使得 |i-j| <= knums[j] == key。时间复杂度 O(n²)。

  2. 优化思路:先找出所有 key 的位置,然后对每个位置计算其影响范围 [pos-k, pos+k],将所有影响范围内的下标加入结果。

  3. 最优解法:使用集合去重。首先遍历数组找到所有等于 key 的下标,然后对每个这样的下标,将其左右各 k 个位置(在数组范围内)的下标都加入集合中。最后将集合转换为有序列表返回。

推荐解法: 集合去重法,既简洁又高效,时间复杂度为 O(nk),在给定约束下表现良好。

核心步骤:

  1. 遍历数组,找到所有值为 key 的下标
  2. 对每个 key 的下标,计算其影响范围 [max(0, pos-k), min(n-1, pos+k)]
  3. 将影响范围内的所有下标加入集合
  4. 将集合转换为有序列表返回

代码实现

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,实际大小取决于重叠情况

相关题目