Taro Logo

Contains Duplicate III

Hard
Netflix logo
Netflix
17 views
Topics:
Arrays

You are given an integer array nums and two integers indexDiff and valueDiff.

Find a pair of indices (i, j) such that:

  1. i != j,
  2. abs(i - j) <= indexDiff.
  3. abs(nums[i] - nums[j]) <= valueDiff, and

Return true if such pair exists or false otherwise.

Example 1:

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:

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.

Can you implement a function to solve this problem efficiently?

Solution


Naive Solution

The naive solution is to iterate through all possible pairs of indices (i, j) and check if they satisfy the given conditions. This approach has a time complexity of O(n^2), where n is the length of the input array nums.

def contains_nearby_almost_duplicate_naive(nums, indexDiff, valueDiff):
    n = len(nums)
    for i in range(n):
        for j in range(i + 1, n):
            if abs(i - j) <= indexDiff and abs(nums[i] - nums[j]) <= valueDiff:
                return True
    return False

Big O Runtime: O(n^2)

Big O Space: O(1)

Optimal Solution

An optimal solution can be achieved using a sliding window and a sorted set (e.g., a TreeSet in Java or SortedList in Python). The idea is to maintain a window of size indexDiff and for each element nums[i], check if there exists an element in the window that satisfies the valueDiff condition.

from sortedcontainers import SortedList

def contains_nearby_almost_duplicate(nums, indexDiff, valueDiff):
    window = SortedList()
    for i, num in enumerate(nums):
        if i > indexDiff:
            window.remove(nums[i - indexDiff - 1])
        
        # Find the smallest element in the window that is >= num - valueDiff
        idx = window.bisect_left(num - valueDiff)
        if idx < len(window) and window[idx] <= num + valueDiff:
            return True
        
        window.add(num)
    
    return False

Explanation:

  1. We use a SortedList called window to maintain the elements within the index difference.
  2. As we iterate through nums, we first check if the current index i is greater than indexDiff. If so, we remove the element that is no longer within the window (i.e., nums[i - indexDiff - 1]).
  3. Then, we use bisect_left to find the index of the smallest element in the window that is greater than or equal to num - valueDiff. This allows us to efficiently check if any element in the window is within the valueDiff range of the current number.
  4. If such an element exists, we return True.
  5. Finally, we add the current number num to the window.

Big O Runtime: O(n log k), where n is the length of nums and k is the indexDiff

Big O Space: O(k), where k is the indexDiff

Edge Cases

  • Empty array: The algorithm should return false if the input array is empty.
  • indexDiff is greater than or equal to the length of the array: The sliding window will cover the entire array.
  • valueDiff is 0: The algorithm should check for duplicate elements within the indexDiff range.
  • Array with all same elements and valueDiff = 0, indexDiff > 0, should return true.