Contains Duplicate III LT220

Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

Example 1:

Input: nums = [1,2,3,1], k = 3, t = 0
Output: true

Example 2:

Input: nums = [1,0,1,1], k = 1, t = 2
Output: true

Example 3:

Input: nums = [1,5,9,1,5,9], k = 2, t = 3
Output: false

Idea 1. Similar to Contains Duplicate II LT219, instead of 0 difference, here is at most t difference, normal hashSet cann't effciently tell if there exists elements (nums[i] - t, nums[i]+t) unless loop the whole range, hence TreeSet could be a good tool, to extract the sorted neighbours of nums[i], and see if the difference to its neighbours is at most t.

Time Complexity: O(NlgK)

Space complexity: O(K)

 1 import java.util.NavigableSet;
 2 class Solution {
 3     public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
 4         TreeSet<Integer> window = new TreeSet<>();
 5         
 6         for(int right = 0; right < nums.length; ++right) {
 7             Integer prev = window.floor(nums[right]);
 8             Integer next = window.higher(nums[right]);
 9             
10             if((prev != null && (long)nums[right] - prev <= t)
11                || (next != null && (long)next - nums[right] <= t)) {
12                 return true;
13             }
14             window.add(nums[right]);
15             
16             if(right >= k) {
17                 window.remove(nums[right-k]);
18             }
19         }
20         
21         return false;
22     }
23 }

Idea 2. Interesting idea with buckets to map the range[0...t] to a bucket slot, if nums[i] and nums[j] map to the same bucket, it means that their diff is at most, the difference between the sorted tail of buckets[k] and the sorted head of buckets[k+1] could be in range as well, so need to check two neighbour buckets[k-1] and buckets[k+1].

Note. integer overflow, only convert to long if needed, for example during calcuation (+/-), but no need to change Map<Integer, Integer> to Map<Long, Integer>, also t + 1 could be overflow, do (long)t + 1 instead.

Time complexity: O(N)

Space complexity: O(N)

 1 class Solution {
 2     public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
 3         if(t < 0) {
 4             return false;
 5         }
 6         
 7         Map<Integer, Integer> buckets = new HashMap<>();
 8         
 9         for(int right = 0; right < nums.length; ++right) {
10             int bucketKey = (int)( ( (long) nums[right] - Integer.MIN_VALUE ) / ( (long)t+1) );
11             
12             if(buckets.containsKey(bucketKey)
13               || (buckets.containsKey(bucketKey-1) && (long)nums[right] - buckets.get(bucketKey-1) <= t)
14               || (buckets.containsKey(bucketKey+1) && (long)buckets.get(bucketKey+1) - nums[right] <= t)) {
15                 return true;
16             }
17             buckets.put(bucketKey, nums[right]);
18             
19             if(right >= k) {
20                 int key = (int)( ( (long)nums[right-k] - Integer.MIN_VALUE ) / ( (long)t+1) );
21                 buckets.remove(key);
22             }
23         }
24         
25         return false;
26     }
27 }

posted on 2019-05-12 07:30  一直走在路上  阅读(86)  评论(0编辑  收藏  举报

导航