Problem
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i]
and nums[j]
is at most t
and the difference between i
and j
is at most k
.
OR
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
, and
Return true
if such pair exists or false
otherwise.
Examples
Example 1:
Input: nums = [1,2,3,1], indexDiff = 3, valueDiff = 0
Output: true
Explanation: 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
Example 2:
Input: nums = [1,5,9,1,5,9], indexDiff = 2, valueDiff = 3
Output: false
Explanation: After trying all the possible pairs (i, j), we cannot satisfy the three conditions, so we return false.
Solution
Method 1 - Using TreeSet and Sliding Window
To solve the problem, we can use a sliding window approach and a data structure that allows efficient insertion, deletion, and lookup. A TreeSet
provides these capabilities with logarithmic time complexity for each operation, making it a good choice for this problem.
Approach
- Use a
TreeSet
to maintain a sliding window ofindexDiff
ork
size. - For each element in
nums
:- Use
TreeSet.floor()
andTreeSet.ceiling()
to find the nearest elements within thevalueDiff
ort
. - If any such element is found, return
true
. - Maintain the sliding window by adding the current element to the set and removing the element that is
indexDiff
ork
positions before the current index.
- Use
Lets see what floor and ceiling mean.
floor(x) = Largest element <= to the x.
ceiling(x) = Smallest element >= to the x.
So, if TreeSet has following elements:
set = [1, 2, 4, 5]
Then, here are floor and ceiling of 3:
floor(3) = 2
ceiling(3) = 4
Code
Java
public class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (nums == null || nums.length < 2 || k < 1 || t < 0) {
return false;
}
// TreeSet to maintain the sliding window of `k` size
TreeSet<Integer> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
// Check the floor within the t range
Integer floor = set.floor(num);
if (floor != null && Math.abs(num - floor) <= t) {
return true;
}
// Check the ceiling within the t range
Integer ceiling = set.ceiling(num);
if (ceiling != null && Math.abs(ceiling - num) <= t) {
return true;
}
set.add(num);
// Maintain the sliding window by removing the element that is `k` positions before the current index
if (i >= k) {
set.remove(nums[i - k]);
}
}
return false;
}
}
Complexity
- ⏰ Time complexity:
O(n log k)
wheren
is the length of the array andk
isindexDiff
. Because, we check each numbers floors and ceils, then add it to set, which takeslog k
, as we only storek
elements in Treeset, and we do it for n elements, henceO(n log k)
- 🧺 Space complexity:
O(k)