220. Contains Duplicate III

problem 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.

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

algorithm thought

这是这个系列的第三题,第二题加入了k表示只看前面k个数。第三题加入了t,代表数字的范围可以再t以内波动。

最开始,我想的是,还是和前一题一样处理,只不过判断是是否存在的时候,使用一个for循环判断这个范围内的值。但是这个题目的测试样例很bug,有个测试样例是INT_MAX,直接超时。

看了discuss,发现有人用桶的方法解这题,我感觉很巧妙。和之前桶排序一样。首先定下桶的大小,这里设为t+1。从INT_MIN开始,每个桶只能放一个数。如果出现相同的桶,那么就可以直接返回true,因为同一个桶中,最大的差值就是t。然后还需要在这个桶的前一个和后一个桶中找数,判断差值是否小于t。如果存在,返回true。通过这种办法,将数字换成桶,再重复利用上题的算法,这里时间复杂度可以到O(n)

code

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        if(k<1||t<0)
            return false;
        unordered_map<long,long> ma(k);
        long tmp=static_cast<long>(t);
        for(int i=0;i<nums.size();++i){
            long bucket_num=(static_cast<long>(nums[i])-INT_MIN)/(tmp+1);
            if(ma.count(bucket_num)||
              (ma.count(bucket_num+1)&&ma[bucket_num+1]-nums[i]<=t)||
              (ma.count(bucket_num-1)&&nums[i]-ma[bucket_num-1]<=t))
                return true;
            ma[bucket_num]=nums[i];
            if(i-k>=0){
                ma.erase((static_cast<long>(nums[i-k])-INT_MIN)/(tmp+1)); 
            }
        }
        return false;
    }
};

algorithm analysis

这里遍历一次数组得到结果,时间复杂度O(n)

Last updated