2200. Find All K-Distant Indices in an Array
Problem Description
You are given an integer array nums
(0-indexed), an integer key
, and an integer k
. Your task is to find all "k-distant indices" in the array.
A k-distant index is an index i
where there exists at least one index j
in the array that satisfies both conditions:
- The distance between
i
andj
is at mostk
:|i - j| <= k
- The element at index
j
equals the key:nums[j] == key
In simpler terms, an index i
is k-distant if there's at least one occurrence of key
in the array within k
positions from index i
(either to the left or right).
For example, if nums = [3,4,9,1,3,9,5]
, key = 9
, and k = 1
:
- Index 1 is k-distant because index 2 has value 9 and
|1-2| = 1 <= 1
- Index 2 is k-distant because it contains 9 itself (
|2-2| = 0 <= 1
) - Index 3 is k-distant because index 2 has value 9 and
|3-2| = 1 <= 1
- Index 4 is k-distant because index 5 has value 9 and
|4-5| = 1 <= 1
- Index 5 is k-distant because it contains 9 itself
- Index 6 is k-distant because index 5 has value 9 and
|6-5| = 1 <= 1
The function should return a list of all k-distant indices sorted in increasing order.
Intuition
The problem asks us to identify which indices are "close enough" to any occurrence of the key
value in the array. The straightforward way to think about this is to check each index one by one and determine if it qualifies as k-distant.
For any given index i
, we need to answer: "Is there at least one occurrence of key
within distance k
from this position?" To answer this, we can scan through the entire array looking for positions where nums[j] == key
, and check if any of these positions satisfy |i - j| <= k
.
The brute force approach naturally emerges from this line of thinking:
- For each possible index
i
in the array (from 0 to n-1) - Check all indices
j
in the array to see ifnums[j] == key
- If we find even one such
j
where the distance|i - j| <= k
, theni
is k-distant - Add all qualifying indices to our result
This direct translation of the problem statement into code gives us a solution that's easy to understand and implement. While checking every pair of indices (i, j)
might seem inefficient with O(nΒ²)
time complexity, it guarantees we won't miss any k-distant indices.
The key insight is that we don't need to find all indices j
where nums[j] == key
for each i
- we just need to know if at least one exists within the distance constraint. This is why we can use the any()
function in Python, which stops as soon as it finds the first qualifying j
, providing a slight optimization in practice.
Learn more about Two Pointers patterns.
Solution Approach
The solution implements a brute force enumeration approach to find all k-distant indices.
Algorithm Steps:
-
Initialize the result list: Create an empty list
ans
to store all k-distant indices that we find. -
Get array length: Store the length of the input array in variable
n
for convenient access. -
Outer loop - Check each index: Enumerate through each index
i
from 0 ton-1
. Each indexi
is a candidate for being k-distant. -
Inner check - Verify k-distance condition: For each index
i
, we need to check if there exists at least one indexj
in the entire array where:nums[j] == key
(the element at positionj
equals our target key)|i - j| <= k
(the distance betweeni
andj
is at mostk
)
This is accomplished using Python's
any()
function with a generator expression that iterates through all possible indicesj
from 0 ton-1
. -
Add qualifying indices: If the condition in step 4 is satisfied (meaning
i
is indeed k-distant), appendi
to the answer list. -
Return sorted result: Since we iterate through indices in increasing order (0 to
n-1
), the resulting list is already sorted in increasing order, so we can directly returnans
.
Implementation Details:
The expression any(abs(i - j) <= k and nums[j] == key for j in range(n))
efficiently checks if index i
is k-distant:
- It iterates through all possible values of
j
- For each
j
, it checks both conditions: distance constraint (abs(i - j) <= k
) and value match (nums[j] == key
) - Returns
True
as soon as it finds the firstj
that satisfies both conditions - Returns
False
if no suchj
exists after checking all indices
Time Complexity: O(nΒ²)
where n
is the length of the array, as we check every pair of indices (i, j)
.
Space Complexity: O(1)
extra space (not counting the output array), as we only use a constant amount of additional variables.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a small example to illustrate how the algorithm works.
Example Input:
nums = [2, 3, 2, 4, 3]
key = 3
k = 2
Step-by-step execution:
Checking index i = 0:
- We check if there's any
j
wherenums[j] == 3
and|0 - j| <= 2
- j = 0:
nums[0] = 2 β 3
β - j = 1:
nums[1] = 3 == 3
β and|0 - 1| = 1 <= 2
β - Found a match! Index 0 is k-distant β Add 0 to result
Checking index i = 1:
- We check if there's any
j
wherenums[j] == 3
and|1 - j| <= 2
- j = 0:
nums[0] = 2 β 3
β - j = 1:
nums[1] = 3 == 3
β and|1 - 1| = 0 <= 2
β - Found a match! Index 1 is k-distant β Add 1 to result
Checking index i = 2:
- We check if there's any
j
wherenums[j] == 3
and|2 - j| <= 2
- j = 0:
nums[0] = 2 β 3
β - j = 1:
nums[1] = 3 == 3
β and|2 - 1| = 1 <= 2
β - Found a match! Index 2 is k-distant β Add 2 to result
Checking index i = 3:
- We check if there's any
j
wherenums[j] == 3
and|3 - j| <= 2
- j = 0:
nums[0] = 2 β 3
β - j = 1:
nums[1] = 3 == 3
β and|3 - 1| = 2 <= 2
β - Found a match! Index 3 is k-distant β Add 3 to result
Checking index i = 4:
- We check if there's any
j
wherenums[j] == 3
and|4 - j| <= 2
- j = 0:
nums[0] = 2 β 3
β - j = 1:
nums[1] = 3 == 3
β but|4 - 1| = 3 > 2
β - j = 2:
nums[2] = 2 β 3
β - j = 3:
nums[3] = 4 β 3
β - j = 4:
nums[4] = 3 == 3
β and|4 - 4| = 0 <= 2
β - Found a match! Index 4 is k-distant β Add 4 to result
Final Result: [0, 1, 2, 3, 4]
All indices are k-distant because each index is within distance 2 of at least one occurrence of the key value 3 (which appears at indices 1 and 4).
Solution Implementation
1class Solution:
2 def findKDistantIndices(self, nums: List[int], key: int, k: int) -> List[int]:
3 """
4 Find all indices i where there exists at least one index j such that:
5 - nums[j] == key
6 - |i - j| <= k
7
8 Args:
9 nums: List of integers to search through
10 key: Target value to find in the array
11 k: Maximum distance between indices i and j
12
13 Returns:
14 List of indices that are within k distance of any occurrence of key
15 """
16 result = []
17 n = len(nums)
18
19 # Check each index i in the array
20 for i in range(n):
21 # Check if there exists any index j where nums[j] == key and |i - j| <= k
22 is_k_distant = any(
23 abs(i - j) <= k and nums[j] == key
24 for j in range(n)
25 )
26
27 # If condition is satisfied, add current index to result
28 if is_k_distant:
29 result.append(i)
30
31 return result
32
1class Solution {
2 /**
3 * Finds all indices that are within k distance from any index where nums[j] == key.
4 * An index i is k-distant if there exists an index j such that |i - j| <= k and nums[j] == key.
5 *
6 * @param nums the input array
7 * @param key the target value to search for
8 * @param k the maximum distance allowed
9 * @return a list of all k-distant indices in ascending order
10 */
11 public List<Integer> findKDistantIndices(int[] nums, int key, int k) {
12 int arrayLength = nums.length;
13 List<Integer> result = new ArrayList<>();
14
15 // Check each index i to see if it's k-distant from any key
16 for (int i = 0; i < arrayLength; i++) {
17 // For current index i, check if there's any index j with nums[j] == key
18 // within k distance
19 for (int j = 0; j < arrayLength; j++) {
20 // Check if j contains the key and is within k distance from i
21 if (Math.abs(i - j) <= k && nums[j] == key) {
22 // Found a valid j, so i is k-distant
23 result.add(i);
24 break; // No need to check other j values for this i
25 }
26 }
27 }
28
29 return result;
30 }
31}
32
1class Solution {
2public:
3 vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {
4 int n = nums.size();
5 vector<int> result;
6
7 // Iterate through each index i in the array
8 for (int i = 0; i < n; ++i) {
9 // Check if current index i is k-distant from any index j where nums[j] == key
10 for (int j = 0; j < n; ++j) {
11 // If distance between i and j is at most k AND nums[j] equals key
12 if (abs(i - j) <= k && nums[j] == key) {
13 // Add index i to result as it satisfies the k-distant condition
14 result.push_back(i);
15 // Break inner loop since we found at least one valid j for current i
16 break;
17 }
18 }
19 }
20
21 return result;
22 }
23};
24
1/**
2 * Finds all k-distant indices in the array.
3 * A k-distant index i is one where there exists an index j such that:
4 * - |i - j| <= k
5 * - nums[j] === key
6 *
7 * @param nums - The input array of numbers
8 * @param key - The target value to search for
9 * @param k - The maximum distance between indices
10 * @returns An array of all k-distant indices in ascending order
11 */
12function findKDistantIndices(nums: number[], key: number, k: number): number[] {
13 const arrayLength: number = nums.length;
14 const resultIndices: number[] = [];
15
16 // Check each index i to see if it's k-distant
17 for (let i = 0; i < arrayLength; ++i) {
18 // For current index i, check if any index j within k distance contains the key
19 for (let j = 0; j < arrayLength; ++j) {
20 // Check if j is within k distance from i and contains the key value
21 if (Math.abs(i - j) <= k && nums[j] === key) {
22 // Found a valid j, so i is a k-distant index
23 resultIndices.push(i);
24 // No need to check other j values for this i
25 break;
26 }
27 }
28 }
29
30 return resultIndices;
31}
32
Time and Space Complexity
The time complexity is O(n^2)
, where n
is the length of the array nums
. This is because we have a nested loop structure - the outer loop iterates through all n
indices with for i in range(n)
, and for each index i
, the inner comprehension any(abs(i - j) <= k and nums[j] == key for j in range(n))
iterates through all n
indices again to check if there exists any index j
where nums[j] == key
and the distance condition abs(i - j) <= k
is satisfied. This results in n * n = n^2
operations.
The space complexity is O(1)
for auxiliary space (excluding the output array). The only extra variables used are loop counters and temporary values in the comprehension. However, if we consider the output array ans
, the total space complexity would be O(n)
in the worst case when all indices satisfy the condition and need to be included in the result.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Inefficient Time Complexity for Large Arrays
The current O(nΒ²) solution checks every possible pair of indices, which becomes extremely slow for large arrays. Even when there are only a few occurrences of key
, we still check all n indices for each position.
Example scenario: If nums
has 10,000 elements but only contains the key
once at index 5000, and k = 2
, the current solution still performs 100,000,000 operations to find just 5 k-distant indices.
Optimized Solution:
class Solution:
def findKDistantIndices(self, nums: List[int], key: int, k: int) -> List[int]:
# First, find all indices where key appears
key_indices = [j for j, num in enumerate(nums) if num == key]
# If no key found, return empty list
if not key_indices:
return []
result = []
n = len(nums)
# For each index i, check if it's within k distance of any key index
for i in range(n):
# Use binary search or early termination for efficiency
for j in key_indices:
if abs(i - j) <= k:
result.append(i)
break # Found one match, no need to check other key indices
return result
2. Even Better: Range Merging Approach
A more elegant solution treats each occurrence of key
as creating a "range" of k-distant indices and merges overlapping ranges:
class Solution:
def findKDistantIndices(self, nums: List[int], key: int, k: int) -> List[int]:
key_indices = [j for j, num in enumerate(nums) if num == key]
if not key_indices:
return []
result = []
n = len(nums)
# For each key position, mark the range [j-k, j+k] as k-distant
for j in key_indices:
start = max(0, j - k)
end = min(n - 1, j + k)
# Add all indices in this range (avoiding duplicates)
for i in range(start, end + 1):
if not result or result[-1] < i:
result.append(i)
return result
3. Memory Optimization Using Set
When dealing with potential duplicates and needing sorted output, using a set can be cleaner:
class Solution:
def findKDistantIndices(self, nums: List[int], key: int, k: int) -> List[int]:
result_set = set()
n = len(nums)
# Find all positions of key
for j in range(n):
if nums[j] == key:
# Add all indices within k distance
for i in range(max(0, j - k), min(n, j + k + 1)):
result_set.add(i)
return sorted(result_set)
This approach is O(n*k) in the worst case but typically performs much better than O(nΒ²) when the key appears infrequently or k is small.
Which of the following uses divide and conquer strategy?
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!