跳转至

3488. 距离最小相等元素查询

题目描述

给你一个 循环 数组 nums 和一个数组 queries 。

对于每个查询 i ,你需要找到以下内容:

  • 数组 nums 中下标 queries[i] 处的元素与 任意 其他下标 j(满足 nums[j] == nums[queries[i]])之间的 最小 距离。如果不存在这样的下标 j,则该查询的结果为 -1

返回一个数组 answer,其大小与 queries 相同,其中 answer[i] 表示查询i的结果。

 

示例 1:

输入: nums = [1,3,1,4,1,3,2], queries = [0,3,5]

输出: [2,-1,3]

解释:

  • 查询 0:下标 queries[0] = 0 处的元素为 nums[0] = 1 。最近的相同值下标为 2,距离为 2。
  • 查询 1:下标 queries[1] = 3 处的元素为 nums[3] = 4 。不存在其他包含值 4 的下标,因此结果为 -1。
  • 查询 2:下标 queries[2] = 5 处的元素为 nums[5] = 3 。最近的相同值下标为 1,距离为 3(沿着循环路径:5 -> 6 -> 0 -> 1)。

示例 2:

输入: nums = [1,2,3,4], queries = [0,1,2,3]

输出: [-1,-1,-1,-1]

解释:

数组 nums 中的每个值都是唯一的,因此没有下标与查询的元素值相同。所有查询的结果均为 -1。

 

提示:

  • 1 <= queries.length <= nums.length <= 105
  • 1 <= nums[i] <= 106
  • 0 <= queries[i] < nums.length

解法

方法一:环形数组 + 哈希表

根据题目描述,我们需要找出数组每个元素与上一个相同元素的最小距离,以及与下一个相同元素的最小距离。并且,由于数组是循环的,所以我们需要考虑数组的环形特性,我们可以将数组扩展为原数组的两倍,然后使用哈希表 \(\textit{left}\)\(\textit{right}\) 分别记录每个元素上一次出现的位置和下一次出现的位置,计算出每个位置的元素与另一个相同元素的最小距离,记录在数组 \(\textit{d}\) 中。最后,我们遍历查询,对于每个查询 \(i\),我们取 \(\textit{d}[i]\)\(\textit{d}[i+n]\) 中的最小值,如果该值大于等于 \(n\),则说明不存在与查询元素相同的元素,返回 \(-1\),否则返回该值。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\) 为数组 \(\textit{nums}\) 的长度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution:
    def solveQueries(self, nums: List[int], queries: List[int]) -> List[int]:
        n = len(nums)
        m = n << 1
        d = [m] * m
        left = {}
        for i in range(m):
            x = nums[i % n]
            if x in left:
                d[i] = min(d[i], i - left[x])
            left[x] = i
        right = {}
        for i in range(m - 1, -1, -1):
            x = nums[i % n]
            if x in right:
                d[i] = min(d[i], right[x] - i)
            right[x] = i
        for i in range(n):
            d[i] = min(d[i], d[i + n])
        return [-1 if d[i] >= n else d[i] for i in queries]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
    public List<Integer> solveQueries(int[] nums, int[] queries) {
        int n = nums.length;
        int m = n * 2;
        int[] d = new int[m];
        Arrays.fill(d, m);

        Map<Integer, Integer> left = new HashMap<>();
        for (int i = 0; i < m; i++) {
            int x = nums[i % n];
            if (left.containsKey(x)) {
                d[i] = Math.min(d[i], i - left.get(x));
            }
            left.put(x, i);
        }

        Map<Integer, Integer> right = new HashMap<>();
        for (int i = m - 1; i >= 0; i--) {
            int x = nums[i % n];
            if (right.containsKey(x)) {
                d[i] = Math.min(d[i], right.get(x) - i);
            }
            right.put(x, i);
        }

        for (int i = 0; i < n; i++) {
            d[i] = Math.min(d[i], d[i + n]);
        }

        List<Integer> ans = new ArrayList<>();
        for (int query : queries) {
            ans.add(d[query] >= n ? -1 : d[query]);
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
public:
    vector<int> solveQueries(vector<int>& nums, vector<int>& queries) {
        int n = nums.size();
        int m = n * 2;
        vector<int> d(m, m);

        unordered_map<int, int> left;
        for (int i = 0; i < m; i++) {
            int x = nums[i % n];
            if (left.count(x)) {
                d[i] = min(d[i], i - left[x]);
            }
            left[x] = i;
        }

        unordered_map<int, int> right;
        for (int i = m - 1; i >= 0; i--) {
            int x = nums[i % n];
            if (right.count(x)) {
                d[i] = min(d[i], right[x] - i);
            }
            right[x] = i;
        }

        for (int i = 0; i < n; i++) {
            d[i] = min(d[i], d[i + n]);
        }

        vector<int> ans;
        for (int query : queries) {
            ans.push_back(d[query] >= n ? -1 : d[query]);
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
func solveQueries(nums []int, queries []int) []int {
    n := len(nums)
    m := n * 2
    d := make([]int, m)
    for i := range d {
        d[i] = m
    }

    left := make(map[int]int)
    for i := 0; i < m; i++ {
        x := nums[i%n]
        if idx, exists := left[x]; exists {
            d[i] = min(d[i], i-idx)
        }
        left[x] = i
    }

    right := make(map[int]int)
    for i := m - 1; i >= 0; i-- {
        x := nums[i%n]
        if idx, exists := right[x]; exists {
            d[i] = min(d[i], idx-i)
        }
        right[x] = i
    }

    for i := 0; i < n; i++ {
        d[i] = min(d[i], d[i+n])
    }

    ans := make([]int, len(queries))
    for i, query := range queries {
        if d[query] >= n {
            ans[i] = -1
        } else {
            ans[i] = d[query]
        }
    }
    return ans
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function solveQueries(nums: number[], queries: number[]): number[] {
    const n = nums.length;
    const m = n * 2;
    const d: number[] = Array(m).fill(m);

    const left = new Map<number, number>();
    for (let i = 0; i < m; i++) {
        const x = nums[i % n];
        if (left.has(x)) {
            d[i] = Math.min(d[i], i - left.get(x)!);
        }
        left.set(x, i);
    }

    const right = new Map<number, number>();
    for (let i = m - 1; i >= 0; i--) {
        const x = nums[i % n];
        if (right.has(x)) {
            d[i] = Math.min(d[i], right.get(x)! - i);
        }
        right.set(x, i);
    }

    for (let i = 0; i < n; i++) {
        d[i] = Math.min(d[i], d[i + n]);
    }

    return queries.map(query => (d[query] >= n ? -1 : d[query]));
}

评论