[Summary] contains duplicate I, II, III

I – Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

II – Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k.

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.

解题思路:
I – 用set记录是否出现重复的数字
if (!set.add(nums[i])) return true

II – 用set,但超出|i-j| k) set.remove(nums[i-k-1])

III – basic idea: 用bucketing,例如t = 3,将[0,1,2,3]对应到0,[4,5,6,7]对应到1,…这样和某一个数字相差<=3的数字,一定在自己对应的bucket,或相邻的bucket中。因此mapping function: nums[i] / (t+1).
details:
1.问题:nums[i]可能<0, [-3,-2,-1,0]和[0,1,2,3]在经过bucket mapping之后,都将对应到0. 解决办法:nums[i] = (long)nums[i] – Integer.MIN_VALUE,让所有数字都从0开始。
2.bucket size选t+1,如果选t的话,t可能是0

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

            map.put(bucket, rep);
        }

        return false;

    }