LeetCode Solutions

220. Contains Duplicate III

Time: $O(n\log k)$

Space: $O(k)$

			

class Solution {
 public:
  bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    set<long> window;

    for (int i = 0; i < nums.size(); ++i) {
      const auto it = window.lower_bound(static_cast<long>(nums[i]) - t);
      if (it != cend(window) && *it - nums[i] <= t)
        return true;
      window.insert(nums[i]);
      if (i >= k)
        window.erase(nums[i - k]);
    }

    return false;
  }
};
			

class Solution {
  public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
    TreeSet<Long> set = new TreeSet<>();

    for (int i = 0; i < nums.length; ++i) {
      final long num = (long) nums[i];
      final Long ceiling = set.ceiling(num); // The smallest num >= nums[i]
      if (ceiling != null && ceiling - num <= t)
        return true;
      final Long floor = set.floor(num); // The largest num <= nums[i]
      if (floor != null && num - floor <= t)
        return true;
      set.add(num);
      if (i >= k)
        set.remove((long) nums[i - k]);
    }

    return false;
  }
}
			

class Solution {
 public:
  bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    if (nums.empty() || k <= 0 || t < 0)
      return false;

    const long min = *min_element(begin(nums), end(nums));
    const long diff = t + 1L;  // In case of t = 0
    // Use long because corner case INT_MAX - (-1) will overflow
    unordered_map<long, long> bucket;

    for (int i = 0; i < nums.size(); ++i) {
      const long num = nums[i];
      const long key = getKey(num, min, diff);
      if (bucket.count(key))  // Current bucket
        return true;
      if (bucket.count(key - 1) &&
          num - bucket[key - 1] < diff)  // Left adjacent bucket
        return true;
      if (bucket.count(key + 1) &&
          bucket[key + 1] - num < diff)  // Right adjacent bucket
        return true;
      bucket[key] = num;
      if (i >= k)
        bucket.erase(getKey(nums[i - k], min, diff));
    }

    return false;
  }

 private:
  int getKey(long num, long min, long diff) {
    return (num - min) / diff;
  }
};