2905. Find Indices With Index and Value Difference II
Problem Description
In this problem, you are given an array nums
of integers and two additional integers, indexDifference
and valueDifference
. Your task is to find any two indices i
and j
such that the following two conditions are satisfied:
- The absolute difference between the indices
i
andj
is greater than or equal toindexDifference
, that isabs(i - j) >= indexDifference
. - The absolute difference between the values at indices
i
andj
in the arraynums
is greater than or equal tovalueDifference
, that isabs(nums[i] - nums[j]) >= valueDifference
.
You need to return an array where the first element is the index i
and the second element is the index j
. If no such pair of indices exists, you should return [-1, -1]
.
Note that the indices i
and j
may be the same, which implies that the constraints do not preclude the possibility of comparing an element with itself, as long as the index difference is non-existent (zero).
Intuition
The intuition behind the solution involves iterating through the array while keeping track of the minimum and maximum values seen so far, separated by at least indexDifference
. As we traverse the array from the starting index set by indexDifference
, we keep updating the minimum index mi
and the maximum index mx
when a smaller or larger element appears in the range that satisfies the index difference condition.
During this traversal:
- We want to check if the current maximum value we have seen so far (
nums[mx]
) minus the current value (nums[i]
) is greater than or equal tovalueDifference
. If this condition is met, we have found a valid pair of indices[mx, i]
and return them. - Similarly, we check if the current value (
nums[i]
) minus the current minimum value we have seen so far (nums[mi]
) is also greater than or equal tovalueDifference
. If this condition is met, we have found another valid pair of indices[mi, i]
and return them.
The reason we can perform these checks is that by maintaining the smallest and largest values with the required index difference, we maximize the chances of finding a valid valueDifference
. If no such pair is found throughout the traversal, we return [-1, -1]
indicating the absence of such a pair of indices satisfying the given conditions.
Solution Approach
The solution uses a simple linear scan approach, enhanced with clever tracking of minimum and maximum values found within a valid index difference range. Here's the breakdown of the approach step-by-step, using the Solution provided:
- The function
findIndices
takes the arraynums
,indexDifference
, andvalueDifference
as its parameters. - Two pointers,
mi
andmx
, are initialized to0
. They will keep track of the indices of the minimum and maximum values found within the range specified by theindexDifference
. - We use a
for
loop to iterate over the array starting from theindexDifference
up to the length of the array. This ensures that we always have a range of elements where the earliest element (nums[j]
) is exactlyindexDifference
apart from the current element (nums[i]
). - At each iteration, we calculate
j
to point to the element which isindexDifference
behind the current elementi
. - Next, we update the
mi
andmx
pointers if the value atnums[j]
is less than the current minimum or greater than the current maximum, respectively. - Immediately after updating
mi
andmx
, we perform the check for thevalueDifference
condition:- If the difference between the current element's value (
nums[i]
) and the minimum value (nums[mi]
) is greater than or equal tovalueDifference
, we return the indices[mi, i]
as a result. - Similarly, if the difference between the maximum value (
nums[mx]
) and the current element's value is greater than or equal tovalueDifference
, we return the indices[mx, i]
as a result.
- If the difference between the current element's value (
- If we do not find any indices that satisfy both conditions by the end of the loop, we return
[-1, -1]
.
Let's detail the functionality with the help of an example:
Suppose nums = [5, 3, 4, 2, 1, 3]
, indexDifference = 3
, and valueDifference = 2
.
- We initialize
mi = mx = 0
. - When
i = 3
(indexDifference = 3
),j = 0
. Now,nums[i] = 2
andnums[j] = 5
.mi
is unchanged asnums[j] < nums[mi]
does not hold true, butnums[j] > nums[mx]
holds true somx
is updated to0
. - Next checks for value difference,
nums[i] - nums[mi] < valueDifference
andnums[mx] - nums[i]
is5 - 2 = 3
which is greater thanvalueDifference
so the function returns[mx, i]
which is[0,3]
.
The solution is efficient, traversing the list only once (O(n)), with constant space complexity (O(1)), as it doesn't require additional storage proportional to the input size.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example to illustrate the solution approach using the following inputs: nums = [1, 5, 9, 3, 5]
, indexDifference = 2
, and valueDifference = 4
.
- We initialize pointers
mi = mx = 0
to keep track of the indices of the minimum and maximum values found. - We iterate over the array starting from
i = indexDifference
, which is2
in this case. At i = 2,nums[i] = nums[2] = 9
. - For each
i
, we calculatej = i - indexDifference
. Wheni = 2
,j = 2 - 2 = 0
. - Now we compare the current element
nums[i]
withnums[mi]
andnums[mx]
to check if we need to updatemi
ormx
. Sincenums[mi] = nums[0] = 1
andnums[mx] = nums[0] = 1
, and the current elementnums[i] = 9
is greater than both, we updatemx
to2
. - We check the
valueDifference
condition with the updated indices. Here,nums[mx] - nums[i]
is0
sincemx = i = 2
. However, this check is redundant now as it's comparing the element with itself. - We move to the next iteration, with
i = 3
, andnums[i] = nums[3] = 3
, and we calculatej = i - indexDifference = 1
. Now,nums[j] = nums[1] = 5
. At this point,mi
remains0
becausenums[1] > nums[0]
, but we don't updatemx
because it currently points to2
where the value is higher (9
). - We check
valueDifference
again for these values. We find thatabs(nums[mx] - nums[i]) = abs(9 - 3) = 6
, which is greater thanvalueDifference
, so we return the indices[mx, i]
which is[2, 3]
. - Since we have found a valid pair that satisfies the conditions, the function terminates and returns
[2, 3]
.
Through this example, we demonstrated how the algorithm scans the list while maintaining the indices of the minimum and maximum values to efficiently find a valid pair [i, j]
that satisfies both the index difference and value difference conditions. If no such pair is found by the time the algorithm has iterated through the entire array, it would return [-1, -1]
.
Solution Implementation
1from typing import List
2
3class Solution:
4 def findIndices(self, nums: List[int], index_diff: int, value_diff: int) -> List[int]:
5 # Initialize variables to keep track of the minimum and maximum values within the window
6 min_index = max_index = 0
7
8 # Iterate through the list starting from the index that allows the full index_diff window
9 for i in range(index_diff, len(nums)):
10 # Calculate the starting index of the window
11 window_start = i - index_diff
12
13 # Update min_index if a new minimum is found within the window
14 if nums[window_start] < nums[min_index]:
15 min_index = window_start
16
17 # Update max_index if a new maximum is found within the window
18 if nums[window_start] > nums[max_index]:
19 max_index = window_start
20
21 # Check if the current number minus the minimum number within the window meets the value_diff
22 if nums[i] - nums[min_index] >= value_diff:
23 # If the condition is met, return the indices that represent the difference
24 return [min_index, i]
25
26 # Check if the maximum number within the window minus the current number meets the value_diff
27 if nums[max_index] - nums[i] >= value_diff:
28 # If the condition is met, return the indices that represent the difference
29 return [max_index, i]
30
31 # If no such indices are found, return [-1, -1]
32 return [-1, -1]
33
1class Solution {
2
3 // Method to find the indices of two elements in the array satisfying given conditions
4 public int[] findIndices(int[] nums, int indexDifference, int valueDifference) {
5 // Initialize minimum and maximum element indices
6 int minIndex = 0;
7 int maxIndex = 0;
8
9 // Iterate through the array starting from the indexDifference position
10 for (int i = indexDifference; i < nums.length; ++i) {
11 int j = i - indexDifference; // Calculate the index to compare with
12
13 // Update the minimum index if a smaller value is found
14 if (nums[j] < nums[minIndex]) {
15 minIndex = j;
16 }
17
18 // Update the maximum index if a larger value is found
19 if (nums[j] > nums[maxIndex]) {
20 maxIndex = j;
21 }
22
23 // Check if the current value and the value at minIndex have the required valueDifference
24 if (nums[i] - nums[minIndex] >= valueDifference) {
25 return new int[] {minIndex, i}; // Return the indices if condition is satisfied
26 }
27
28 // Check if the value at maxIndex and the current value have the required valueDifference
29 if (nums[maxIndex] - nums[i] >= valueDifference) {
30 return new int[] {maxIndex, i}; // Return the indices if condition is satisfied
31 }
32 }
33
34 // If no such pair is found, return [-1, -1]
35 return new int[] {-1, -1};
36 }
37}
38
1#include <vector>
2using namespace std;
3
4class Solution {
5public:
6 vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
7 int minIndex = 0; // Initialize variable to keep track of the minimum value's index
8 int maxIndex = 0; // Initialize variable to keep track of the maximum value's index
9
10 // Iterate through the vector, starting from the index specified by indexDifference
11 for (int i = indexDifference; i < nums.size(); ++i) {
12 int comparisonIndex = i - indexDifference; // Calculate the comparison index
13
14 // Update minIndex if the current comparison value is smaller than the smallest found so far
15 if (nums[comparisonIndex] < nums[minIndex]) {
16 minIndex = comparisonIndex;
17 }
18
19 // Update maxIndex if the current comparison value is greater than the largest found so far
20 if (nums[comparisonIndex] > nums[maxIndex]) {
21 maxIndex = comparisonIndex;
22 }
23
24 // If the value difference between the current index and the minIndex is greater than or equal to valueDifference, return these indices
25 if (nums[i] - nums[minIndex] >= valueDifference) {
26 return {minIndex, i};
27 }
28
29 // If the value difference between the maxIndex and the current index is greater than or equal to valueDifference, return these indices
30 if (nums[maxIndex] - nums[i] >= valueDifference) {
31 return {maxIndex, i};
32 }
33 }
34
35 // If no such indices are found that satisfy the conditions, return {-1, -1}
36 return {-1, -1};
37 }
38};
39
1function findIndices(nums: number[], indexDifference: number, valueDifference: number): number[] {
2 // Initialize indices for the minimum and maximum values seen so far.
3 let [minIndex, maxIndex] = [0, 0];
4
5 // Iterate through the array, starting from the index specified by the `indexDifference`.
6 for (let currentIndex = indexDifference; currentIndex < nums.length; ++currentIndex) {
7 // Calculate the corresponding index that is `indexDifference` steps before the `currentIndex`.
8 let comparisonIndex = currentIndex - indexDifference;
9
10 // Update the `minIndex` if the current comparison value is lower than the stored minimum.
11 if (nums[comparisonIndex] < nums[minIndex]) {
12 minIndex = comparisonIndex;
13 }
14
15 // Update the `maxIndex` if the current comparison value is higher than the stored maximum.
16 if (nums[comparisonIndex] > nums[maxIndex]) {
17 maxIndex = comparisonIndex;
18 }
19
20 // If the difference between the current value and the minimum value seen so far meets
21 // or exceeds the `valueDifference`, return the indices as an array.
22 if (nums[currentIndex] - nums[minIndex] >= valueDifference) {
23 return [minIndex, currentIndex];
24 }
25
26 // If the difference between the maximum value seen so far and the current value
27 // meets or exceeds the `valueDifference`, return the indices as an array.
28 if (nums[maxIndex] - nums[currentIndex] >= valueDifference) {
29 return [maxIndex, currentIndex];
30 }
31 }
32
33 // If no pairs meet the conditions, return [-1, -1] to indicate failure.
34 return [-1, -1];
35}
36
Time and Space Complexity
Time Complexity
The given code iterates over the array nums
using a single loop starting from indexDifference
up to len(nums)
. For each iteration, the code performs constant-time operations such as comparisons and assignments. These operations do not depend on the size of the input array, except for the iteration that is linear in terms of the number of elements in nums
. Therefore, the time complexity of the code is O(n)
, where n
is the length of the nums
array.
Space Complexity
The space complexity of the code is determined by the extra space used aside from the input. The code uses a constant number of extra variables (mi
, mx
, i
, j
) that do not scale with the size of the input array. Therefore, the space complexity is O(1)
, as there is no additional data structure or space-dependent on the input size used within the function.
Learn more about how to find time and space complexity quickly using problem constraints.
Consider the classic dynamic programming of longest increasing subsequence:
Find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.
For example, the length of LIS for [50, 3, 10, 7, 40, 80]
is 4
and LIS is
[3, 7, 40, 80]
.
What is the recurrence relation?
Recommended Readings
LeetCode 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 we
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time