Jerry's Blog

Recording what I learned everyday

View on GitHub


8 March 2020

LeetCode(108) -- 220

by Jerry Zhang

P220. Contains Duplicate III (Medium)

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.

My Solution

public class P220_ContainsDuplicateIII {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        for (int i = 0; i < nums.length; i++) {
            int length = Math.min(nums.length - i, k + 1);
            int[] copy = new int[length];
            System.arraycopy(nums, i, copy, 0, length);
            Arrays.sort(copy);
            for (int j = 1; j < copy.length; j++) {
                long curr = copy[j];
                long prev = copy[j - 1];
                if (curr - prev <= (long) t) {
                    return true;
                }
            }
        }
        return false;
    }
}

超时了!!

Solution

方法二: Binary Search Tree

用一个TreeSet来保存size最多为k的一个window的所有数。新插入的数,如果它左边或者右边的数跟它的距离小于等于t,则说明找到了正确答案。

注意这里允许的window实际上是k+1,但是每次我们需要在插入之前去比较,所以维护一个size为k的window.

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

72%

方法三: Buckets

分成宽度相等的篮子,往每个篮子里放,如果左右两边的篮子有东西,那么就看是不是离得足够近。

class Solution {
    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<Long, Long> d = new HashMap<>();
        long w = (long) t + 1;
        for (int i = 0; i < nums.length; i++) {
            long m = getID(nums[i], w);
            if (d.containsKey(m)) {
                return true;
            }
            if (d.containsKey(m - 1) && nums[i] - d.get(m - 1) < w) {
                return true;
            }
            if (d.containsKey(m + 1) && d.get(m + 1) - nums[i] < w) {
                return true;
            }
            d.put(m, (long) nums[i]);
            if (i >= k) {
                d.remove(getID(nums[i - k], w));
            }
        }
        return false;
    }
}
tags: LeetCode