220. Contains Duplicate III

来源:互联网 发布:卖跑步装备的淘宝店 编辑:程序博客网 时间:2024/06/05 11:29

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.


K小的时候在index<=K范围内检测是否有和当前元素相差t 以内(临近)的元素,K大的时候以当前元素正负t为范围在hashmap扫描是否重复。

这思路有些投机取巧的意思。

 public static boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t){int len=nums.length;if(len<=1)return false;HashMap<Integer, Integer> hashmap=new HashMap<>(len);for(int i=0;i<len;i++){long num=nums[i];if(k<=100)for(int m=Math.max(i-k,0);m<i;m++){long prenum=hashmap.get(m);if(prenum>=num-t&&prenum<=num+t)return true;}else{for(long m=num-t;m<=num+t;m++)if(hashmap.containsKey(m)&&i-hashmap.get(m)<=k)return true;}hashmap.put(i, (int) num);}return false;}


更好的方法,摘自


https://discuss.leetcode.com/topic/15199/ac-o-n-solution-in-java-using-buckets-with-explanation

https://discuss.leetcode.com/topic/15191/java-o-n-lg-k-solution



-------------------------------------------------------------------------------------------------------------------------

As a followup question, it naturally also requires maintaining a window of size k. When t == 0, it reduces to the previous question so we just reuse the solution.

Since there is now a constraint on the range of the values of the elements to be considered duplicates, it reminds us of doing a range check which is implemented in tree data structure and would take O(LogN) if a balanced tree structure is used, or doing a bucket check which is constant time. We shall just discuss the idea using bucket here.

Bucketing means we map a range of values to the a bucket. For example, if the bucket size is 3, we consider 0, 1, 2 all map to the same bucket. However, if t == 3, (0, 3) is a considered duplicates but does not map to the same bucket. This is fine since we are checking the buckets immediately before and after as well. So, as a rule of thumb, just make sure the size of the bucket is reasonable such that elements having the same bucket is immediately considered duplicates or duplicates must lie within adjacent buckets. So this actually gives us a range of possible bucket size, i.e. t and t + 1. We just choose it to be t and a bucket mapping to be num / t.

Another complication is that negative ints are allowed. A simple num / t just shrinks everything towards 0. Therefore, we can just reposition every element to start from Integer.MIN_VALUE.

 public class Solution {    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {        if (k < 1 || t < 0) return false;        Map<Long, Long> map = new HashMap<>();        for (int i = 0; i < nums.length; i++) {            long remappedNum = (long) nums[i] - Integer.MIN_VALUE;            long bucket = remappedNum / ((long) t + 1);            if (map.containsKey(bucket)                    || (map.containsKey(bucket - 1) && remappedNum - map.get(bucket - 1) <= t)                        || (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappedNum <= t))                            return true;            if (map.entrySet().size() >= k) {                long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long) t + 1);                map.remove(lastBucket);            }            map.put(bucket, remappedNum);        }        return false;    }}

Edits:

Actually, we can use t + 1 as the bucket size to get rid of the case when t == 0. It simplifies the code. The above code is therefore the updated version.


-----------------------------------------------------------------------------------------------------

This problem requires to maintain a window of size k of the previous values that can be queried for value ranges. The best data structure to do that is Binary Search Tree. As a result maintaining the tree of size k will result in time complexity O(N lg K). In order to check if there exists any value of range abs(nums[i] - nums[j]) to simple queries can be executed both of time complexity O(lg K)

Here is the whole solution using TreeMap.


public class Solution {    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {        if (nums == null || nums.length == 0 || k <= 0) {            return false;        }        final TreeSet<Integer> values = new TreeSet<>();        for (int ind = 0; ind < nums.length; ind++) {            final Integer floor = values.floor(nums[ind] + t);            final Integer ceil = values.ceiling(nums[ind] - t);            if ((floor != null && floor >= nums[ind])                    || (ceil != null && ceil <= nums[ind])) {                return true;            }            values.add(nums[ind]);            if (ind >= k) {                values.remove(nums[ind - k]);            }        }        return false;    }}

0 0
原创粉丝点击