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


思路:
思路1: 笨办法,双重循环,逐个判断,但是超时了。提交结果为40 / 41 test cases passed
思路2: 建立一棵二叉搜索树,保持节数数量小于或等于k。可以想象成一个k大小的滑动窗口,窗口内的元素存储到二叉搜索树中。每次找到比当前元素小的最大值以及比当前元素大的最小值,然后比较一下就可以了。
思路3: 公式(nums[i] - min) / (t+1)可以求出nums[i]所在的bucket下标。为什么要除以t+1?因为两数字之差的取值范围是0~t,共t+1个不同差值,除以t+1可以保证同一个bucket中的数字之差的范围一定是0~t,一定符合要求。前一个bucket或后一个bucket中存放的数字也可能和当前bucket中存放的元素差值小于等于t,这是常识性问题了。此思路是效率最高的。


代码实现:
思路1,超时代码:

class Solution {
public:
    long abs(long a, long b){
        if (a > b){
            return a-b;
        }
        return b-a;
    }
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        for (int i = 0; i < nums.size(); ++i){
            for (int j = i+1; j <= i + k && j < nums.size(); ++j){
                if (abs(nums[i], nums[j]) <= t){
                    return true;
                }
            }
        }
        
        return false;
    }
};

思路2:

class Solution {
public:
    long abs(long a, long b){
        if (a > b){
            return a-b;
        }
        return b-a;
    }
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        if (nums.size() <= 0 || k <= 0 || t < 0){
            return false;
        }
        
        set<long> my_set;
        
        for (int i = 0; i < nums.size(); ++i){
            if (i > k){
                my_set.erase(nums[i-k-1]);
            }
            
            if (my_set.find(nums[i]) != my_set.end()){
                return true;
            }
            auto iter1 = my_set.insert(nums[i]).first;
            auto iter2 = my_set.insert(nums[i]).first;

            if (iter1 != my_set.begin()){ // 小于nums[i]的最大值
                iter1--;
                if (abs(*(iter1), nums[i]) <= t){
                    return true;
                }
            }

            iter2++;
            if (iter2 != my_set.end()){ // 大于nums[i]的最小值
                if (abs(*(iter2), nums[i]) <= t){
                    return true;
                }
            }
        }
        
        return false;
    }
};

思路3:

class Solution {
public:
    long abs(long a, long b){
        if (a > b){
            return a-b;
        }
        return b-a;
    }
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        if (nums.size() <= 0 || k <= 0 || t < 0){
            return false;
        }
        
        unordered_map<long, long> my_map;
        long min = *min_element(nums.begin(), nums.end());
        long diff = t;
        ++diff;
        
        for (int i = 0; i < nums.size(); ++i){
            long buck_i = ((long)nums[i] - min) / diff;
            if (my_map.find(buck_i) != my_map.end()){
                return true;
            }
            if (my_map.find(buck_i-1) != my_map.end() && abs(my_map[buck_i-1], nums[i]) <= t){
                return true;
            }
            if (my_map.find(buck_i+1) != my_map.end() && abs(my_map[buck_i+1], nums[i]) <= t){
                return true;
            }
            my_map[buck_i] = nums[i];
            if (i >= k){
                my_map.erase((nums[i-k] - min) / diff);
            }
        }
        
        return false;
    }
};

参考:
https://www.bilibili.com/video/BV1e7411i7tW?from=search&seid=7991454138907471041

原创文章 299 获赞 2 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zxc120389574/article/details/106078194