You are given an integer array nums
and two integers indexDiff
and valueDiff
.
Find a pair of indices (i, j)
such that:
i != j
,abs(i - j) <= indexDiff
.abs(nums[i] - nums[j]) <= valueDiff
Return true
if such pair exists or false
otherwise.
For example:
nums = [1,2,3,1], indexDiff = 3, valueDiff = 0
should return true
because we can choose (i, j) = (0, 3)
. We satisfy the three conditions:
i != j
--> 0 != 3
abs(i - j) <= indexDiff
--> abs(0 - 3) <= 3
abs(nums[i] - nums[j]) <= valueDiff
--> abs(1 - 1) <= 0
As another example:
nums = [1,5,9,1,5,9], indexDiff = 2, valueDiff = 3
should return false
because after trying all the possible pairs (i, j)
, we cannot satisfy the three conditions.
Can you come up with an efficient algorithm to solve this problem?
The most straightforward approach is to iterate through all possible pairs of indices (i, j) in the array and check if they satisfy the given conditions. This involves nested loops, where the outer loop iterates from i = 0
to n - 1
, and the inner loop iterates from j = 0
to n - 1
. Inside the inner loop, we check if i != j
, abs(i - j) <= indexDiff
, and abs(nums[i] - nums[j]) <= valueDiff
. If all three conditions are met, we return true
. If we finish iterating through all possible pairs without finding a valid pair, we return false
.
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
int n = nums.length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j && Math.abs(i - j) <= indexDiff && Math.abs((long)nums[i] - (long)nums[j]) <= valueDiff) {
return true;
}
}
}
return false;
}
}
The time complexity of the brute force solution is O(n^2), where n is the length of the input array nums
, because of the nested loops.
The space complexity of the brute force solution is O(1), as it uses only a constant amount of extra space.
To improve the time complexity, we can use a sliding window and a TreeSet
. The TreeSet
will store the numbers within the current window of size indexDiff
. For each number nums[i]
, we can use the TreeSet
to find the smallest number greater than or equal to nums[i] - valueDiff
and the largest number less than or equal to nums[i] + valueDiff
. If either of these numbers exist within the TreeSet
, it means we have found a pair that satisfies the conditions.
TreeSet
to store numbers within the sliding window.nums
array from i = 0
to n - 1
.nums[i]
, use treeSet.ceiling(nums[i] - valueDiff)
to find the smallest number in the TreeSet
that is greater than or equal to nums[i] - valueDiff
.nums[i] + valueDiff
, return true
.nums[i]
to the TreeSet
.i >= indexDiff
, remove nums[i - indexDiff]
from the TreeSet
to maintain the sliding window size.false
.import java.util.TreeSet;
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
TreeSet<Long> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
Long floor = set.floor((long)nums[i] + valueDiff);
Long ceiling = set.ceiling((long)nums[i] - valueDiff);
if ((floor != null && floor >= (long)nums[i]) || (ceiling != null && ceiling <= (long)nums[i])) {
return true;
}
set.add((long)nums[i]);
if (i >= indexDiff) {
set.remove((long)nums[i - indexDiff]);
}
}
return false;
}
}
The time complexity of the optimal solution is O(n log k), where n is the length of the input array nums
and k is the window size (indexDiff
). The TreeSet
operations (ceiling
, floor
, add
, and remove
) take O(log k) time each.
The space complexity of the optimal solution is O(k), as the TreeSet
stores at most indexDiff
elements.