3488. Closest Equal Element Queries

  • Array
  • Hash Table
TIME
O(n + q)
SPACE
O(n)
problem on leetcode ↗source on github ↗

Intuition

Precompute the minimum distance to a same-value element for every index. Then queries are O(1) lookups.

Solution

Step 1: Group Indices by Value

indices = defaultdict(list)
for i, num in enumerate(nums):
    indices[num].append(i)

Step 2: Precompute Minimum Distances

For each value with 2+ occurrences:

  • Indices are sorted (we add them in order)
  • For each index, check distance to previous and next (circular)
  • Store minimum in min_dist[i]
for idx_list in indices.values():
    if len(idx_list) < 2:
        continue  # no same-value neighbor
    
    for k, i in enumerate(idx_list):
        prev = idx_list[k - 1]  # wraps around in Python
        nxt = idx_list[(k + 1) % len(idx_list)]
        
        dist_prev = min((i - prev) % n, (prev - i) % n)
        dist_next = min((nxt - i) % n, (i - nxt) % n)
        min_dist[i] = min(dist_prev, dist_next)

Step 3: Answer Queries

return [min_dist[q] for q in queries]

Complexity

  • Time: O(n + q), precompute O(n), queries O(q)
  • Space: O(n)

Edge Cases

  • Unique values → all -1
  • All same value → check prev and next neighbors
  • Two occurrences of a value → both point to each other

Code

from typing import List
from collections import defaultdict


class Solution:
    def solveQueries(self, nums: List[int], queries: List[int]) -> List[int]:
        """
        3488. Closest Equal Element Queries
        Time: O(n + q)
        Space: O(n)
        """
        n = len(nums)

        # Group indices by value
        indices = defaultdict(list)
        for i, num in enumerate(nums):
            indices[num].append(i)

        # Precompute minimum distance for each index
        min_dist = [-1] * n

        for idx_list in indices.values():
            if len(idx_list) < 2:
                continue

            m = len(idx_list)
            for k, i in enumerate(idx_list):
                prev_idx = idx_list[k - 1]
                next_idx = idx_list[(k + 1) % m]

                # Circular distance to previous
                dist_prev = (i - prev_idx) % n
                dist_prev = min(dist_prev, n - dist_prev)

                # Circular distance to next
                dist_next = (next_idx - i) % n
                dist_next = min(dist_next, n - dist_next)

                min_dist[i] = min(dist_prev, dist_next)

        return [min_dist[q] for q in queries]