Video Explanation
This approach uses a SortedSet to maintain a sliding window of up to indexDiff elements (ie.k).
Since the window is kept sorted, we can leverage binary search to efficiently check whether there's a number within valueDiff of the current number.
The algorithm iterates through nums and, for each number, checks whether there is a value within valueDiff in the current window.
- If such a number is found, it returns True.
- Otherwise, it adds the current number to the SortedSet and removes the leftmost (oldest) one when the window size exceeds
indexDiff.
If the entire array is processed without finding such a pair, the function returns False.
from sortedcontainers import SortedSet
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], indexDiff: int, valueDiff: int) -> bool:
if indexDiff <= 0 or valueDiff < 0:
return False
window = SortedSet() # Maintain a sorted sliding window
left = 0
for num in nums:
# Find the smallest number in the window that is ≥ (num - valueDiff), as a potential nearby almost duplicate
pos = window.bisect_left(num - valueDiff)
# Check if that number is within valueDiff of current num
if pos < len(window) and abs(num - window[pos]) <= valueDiff:
return True
window.add(num)
# Ensure window size does not exceed indexDiff
if len(window) > indexDiff:
window.remove(nums[left])
left += 1
return False
Complexity Analysis
Here, n is the input size, and k is the size of the sliding window (ie. indexDiff).
- Time Complexity:
O(n log k)- Each insertion and removal in the SortedSet takes
O(log k), and we perform these operationsntimes, making the time complexityO(n log k).
- Each insertion and removal in the SortedSet takes
- Space Complexity:
O(k)- The SortedSet window holds at most
kelements at any time.
- The SortedSet window holds at most
This approach groups numbers into buckets of size valueDiff + 1 using a hash map (dictionary), while maintaining a sliding window of size indexDiff.
For each number, it checks the current and adjacent buckets for any number within valueDiff.
- If such a number is found, it returns True.
- Otherwise, it adds the current number to its bucket and removes the number that falls outside the sliding window when the window exceeds
indexDiff.
Finally, if no such pair is found after processing all elements, the function returns False.
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], indexDiff: int, valueDiff: int) -> bool:
if indexDiff <= 0 or valueDiff < 0:
return False
buckets = collections.defaultdict(int) # Hashmap to store {bucket_id -> num} in the sliding window
bucket_size = valueDiff + 1 # Ensures numbers in the same bucket are within valueDiff
left = 0
for right, num in enumerate(nums):
bucket_id = num // bucket_size # Python automatically floors integer division for negative numbers
if bucket_id in buckets: # Check if the current bucket already has a number
return True
# Check adjacent buckets for numbers within valueDiff of the current num, as they may be close enough to satisfy the condition
for adj_id in (bucket_id - 1, bucket_id + 1):
if adj_id in buckets and abs(num - buckets[adj_id]) <= valueDiff:
return True
buckets[bucket_id] = num # Add current num to its bucket in the sliding window
# Ensure window size does not exceed indexDiff, by removing the oldest number if needed (sliding window)
if right - left >= indexDiff:
old_num = nums[left]
old_bucket_id = old_num // bucket_size
del buckets[old_bucket_id]
left += 1
return False
Complexity Analysis
Here, n is the input size, and k is the size of the sliding window (ie. indexDiff).
- Time Complexity:
O(n)- Each insertion and removal in the bucket (hash map) takes
O(1)on average. In the worst case, we perform these operations for each of thenelements, resulting in a total time complexity ofO(n).
- Each insertion and removal in the bucket (hash map) takes
- Space Complexity:
O(k)- The bucket window (hashmap) holds at most
kelements at any time due to the sliding window constraint.
- The bucket window (hashmap) holds at most