LeetCode 220. Contains Duplicate III

原题链接在这里:https://leetcode.com/problems/contains-duplicate-iii/

题目:

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.

题解:

借助于TreeSet的subSet函数,看是否有[nums[i]-t, nums[i]+t]范围内的数。

同时维护一个长度为k的窗口,超过了这个长度时就把前面的元素从window中拿出去。

若在window长度范围内,就把nums[i]加进window中。

Note: 

当i>=k, 也就是TreeSet.size()>=k时, 就把这个nums[i-k]从window中拿出去.

这里要先把旧的拿出去才能加新的,因为若是这个要加的新的恰好等于旧的,就会覆盖掉原来的,再拿掉时就会错拿新的。

Time Complexity is O(nlogk). window 的长度为k, TreeSet的contains, insert, delete用时都是O(log k).

Space O(k).

AC Java:

 1 public class Solution {
 2     public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
 3         if(nums == null || nums.length < 2 || k < 1 || t<0){
 4             return false;
 5         }
 6         TreeSet<Long> window = new TreeSet<Long>();
 7         for(int i = 0; i<nums.length; i++){
 8             SortedSet<Long> set = window.subSet((long)nums[i]-t, true, (long)nums[i]+t, true);
 9             if(!set.isEmpty()){
10                 return true;
11             }else{
12                 if(i>=k){
13                     window.remove((long)nums[i-k]);
14                 }
15                 window.add((long)nums[i]);
16             }
17         }
18         return false;
19     }
20 }

也可采用Bucket. e.g. t=2, 就把(0,1,2)放在一个bucket, (3,4,5)放在下一个bucket等等.

当新的num mapped 到的bucket已经有数, 则return true. 并且检查上下各一个bucket. 上面的例子3-2=1也是小于t的.

这里负数也是允许的, -2/3 = 0, 2/3 = 0. -2 和 2 会map到一个bucket下面. 但2-(-2) = 4已经大于t了. 所以map时num都从Integer.MIN_VALUE开始计数.

另为了避免t=0的情况,求bucketNum时,除以(t+1).

Time Complexity: O(nums.length). Space: O(k).

AC Java:

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

类似Contains Duplicate II.

原文地址:https://www.cnblogs.com/Dylan-Java-NYC/p/4924607.html