220. Contains Duplicate III

Description

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.

Solution

TreeSet, time O(n * log(min(n,k)), space O(min(n,k))

维护一个大小为k - 1的TreeSet(内部实现是self-balanced bst),维护到当前元素之前的k - 1个元素,然后调用floor和ceiling api,在TreeSet中找寻范围内的值是否存在即可。

Assume that nn is the total number of nodes in the tree, a balanced binary tree maintains its height in the order of h = \log nh=logn. Thus it supports O(h) = O(\log n)O(h)=O(logn) time for each of insert, search and delete operations.

Here is the entire algorithm in pseudocode:

  • Initialize an empty BST set
  • Loop through the array, for each element x
    • Find the smallest element s in set that is greater than or equal to x, return true if s - x ≤ t
    • Find the greatest element g in set that is smaller than or equal to x, return true if x - g ≤ t
    • Put x in set
    • If the size of the set is larger than k, remove the oldest item.
  • Return false

ceiling
public E ceiling(E e)

Description copied from interface: [NavigableSet](https://docs.oracle.com/javase/7/docs/api/java/util/NavigableSet.html#ceiling(E))

Returns the least element in this set greater than or equal to the given element, or null if there is no such element.

class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        if (nums == null || nums.length < 2 || k < 1 || t < 0) {
            return false;
        }
        
        TreeSet set = new TreeSet<>();    // use long to avoid overflow
        
        for (int i = 0; i < nums.length; ++i) {
            Long floor = set.floor((long) nums[i] + t);
            Long ceiling = set.ceiling((long) nums[i] - t);
            
            if ((floor != null && floor >= nums[i]) 
                || (ceiling != null && ceiling <= nums[i])) {
                return true;
            }
            
            set.add((long) nums[i]);
            
            if (i >= k) {   // keep k closest elements in treeset
                set.remove((long) nums[i - k]);
            }
        }
        
        return false;
    }
}

Bucket sort, time O(n), space O(n)

很妙的解法,详见solution.

public class Solution {
    // Get the ID of the bucket from element value x and bucket width w
    // In Java, `-3 / 5 = 0` and but we need `-3 / 5 = -1`.
    private long getID(long x, long w) {
        return x < 0 ? (x + 1) / w - 1 : x / w;
    }

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        if (t < 0) return false;
        Map d = new HashMap<>();
        long w = (long)t + 1;
        for (int i = 0; i < nums.length; ++i) {
            long m = getID(nums[i], w);
            // check if bucket m is empty, each bucket may contain at most one element
            if (d.containsKey(m))
                return true;
            // check the neighbor buckets for almost duplicate
            if (d.containsKey(m - 1) && Math.abs(nums[i] - d.get(m - 1)) < w)
                return true;
            if (d.containsKey(m + 1) && Math.abs(nums[i] - d.get(m + 1)) < w)
                return true;
            // now bucket m is empty and no almost duplicate in neighbor buckets
            d.put(m, (long)nums[i]);
            if (i >= k) d.remove(getID(nums[i - k], w));
        }
        return false;
    }
}

你可能感兴趣的:(220. Contains Duplicate III)