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(n(logk+t)). window 的长度为k, TreeSet的contains, insert, delete用时都是O(log k). sebSet talkes O(logk + t).
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 }