220. Contains Duplicate III

220. 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 absolutedifference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

Example 1:

Input: nums = [1,2,3,1], k = 3, t = 0
Output: true

Example 2:

Input: nums = [1,0,1,1], k = 1, t = 2
Output: true

Example 3:

Input: nums = [1,5,9,1,5,9], k = 2, t = 3
Output: false

My Solutions:

方法1:brute force

        for(int i = 0; i < nums.length-1; i++) {
            for(int j = i + 1; j < nums.length && j <= i + k; j++) {
                if(Math.abs((long)(nums[i])-nums[j]) <= t) return true;
            }
        }
        return false;

方法2:

对于数组内的一个整数,如果能方便的求出大于它的最小整数和小于它的最大整数,那么我们就可以判断差值是否大于t。能方便的求出最大下限和最小上限,最先想到的数据结构是二叉搜索树BST,因为左孩子就是最大下限,右孩子就是最小上限。

可以用一个大小为k的滑动窗口,将窗口内的元素组织成一个BST,每次向前滑动一步,添加一个新元素,同时删除一个最老的元素,如此不断向前滑动,不断更新BST。如果BST内部有两个元素差值大于t,则返回true,如果直到扫描完数组,BST里都没有出现差值大于k的两个数,则返回false。

对于BST数据结构,可以用现成的,C++里是multiset,Java里是TreeSet

TreeSet数据结构(Java)使用红黑树实现,是平衡二叉树的一种。

该数据结构支持如下操作:

1. floor()方法返set中≤给定元素的最大元素;如果不存在这样的元素,则返回 null。

2. ceiling()方法返回set中≥给定元素的最小元素;如果不存在这样的元素,则返回 null。

e.g. [0,1,2,3,4], 对2来说,floor是1,ceiling是3

复杂度: O(nlgn)

class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        
        if (k < 1 || t < 0) return false;
        
        TreeSet<Integer> set = new TreeSet<>();
        for (int i = 0; i < nums.length; i++) {
            int x = nums[i];
            
            if ((set.floor(x) != null && x <= set.floor(x) + t) 
                || (set.ceiling(x) != null && x >= set.ceiling(x) - t)) {
                return true;
            }
            
            set.add(x); //将此element加入bst
            
            if (i >= k) set.remove(nums[i - k]); //把最先加入set的数删去
        }
        return false;
    }
}

Last updated