美文网首页
220. Contains Duplicate III (M)

220. Contains Duplicate III (M)

作者: Ysgc | 来源:发表于2020-11-19 10:22 被阅读0次

    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

    Constraints:

    0 <= nums.length <= 2 * 104
    -231 <= nums[i] <= 231 - 1
    0 <= k <= 104
    0 <= t <= 231 - 1


    我的方法:

    class Solution {
    public:
        bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
            multiset<long long int> window;
            
            for (int i=0; i<nums.size(); ++i) {
                long int curr_num = nums[i];
                if (window.size() > k and i-k-1>=0) {
                    window.erase(window.lower_bound(nums[i-k-1]));
                }
                
                if (!window.empty()) {
                    long int min_num = *(window.begin());
                    long int max_num = *(window.rbegin());
                    long int left_num = max({min_num, min({max_num, curr_num-t})});
                    long int right_num = max({min_num, min({max_num, curr_num+t})});
                        
                    long int left = *window.lower_bound(left_num);
                    long int right = *window.lower_bound(right_num);
                    if (right != right_num) {
                        auto it =  window.lower_bound(right_num);
                        --it;
                        right = *it;
                    }
                    if (abs(left-curr_num)<=t or abs(right-curr_num)<=t) {
                        return true;
                    }
                }
                window.insert(curr_num);
                
            }
            
            return false;
        }
    };
    

    Runtime: 80 ms, faster than 14.84% of C++ online submissions for Contains Duplicate III.
    Memory Usage: 15.5 MB, less than 12.05% of C++ online submissions for Contains Duplicate III.

    主要思想:用multiset当bucket,sliding window里面动态维护一个mutliset,然后对每个元素找window里面的元素-t 和 元素+t 的lowerbound。

        multiset<int> window = {0,2,4,6};
        cout << *window.lower_bound(1) << endl;
        cout << *window.lower_bound(5) << endl;
    

    的输出是2和6

    注意事项是

    • *window.lower_bound(7)是undefined number,所以不管怎么样都不能超出window max的的范围
    • right_num其实也不能低于window min,否则就会right=begin,*(begin-1)也是undefined
    • 所以结合上面两点必须对curr_num-t ~ +t的氛围clip到window min ~ window max的范围
    • 不知道为什么*(window.lower_bound(right_num) - 1)报错

    看答案
    https://zxi.mytechroad.com/blog/hashtable/leetcode-220-contains-duplicate-iii/
    确实是用multiset,但是用法更巧妙:

    • 首先,set/multiset.insert是有返回值的,就是插入点的iterator
    • 然后其实比较插入点前后就可以了,因为是最近的两个
    • 所以复杂度是O(nlogk)

    结合答案的修改:

    class Solution {
    public:
        bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
            multiset<long> window;
            
            for (int i=0; i<nums.size(); ++i) {
                long curr_num = nums[i];
                if (window.size() > k) {
                    window.erase(window.lower_bound(nums[i-k-1]));
                }
                
                auto it = window.insert(curr_num);
                if (it != window.begin() and curr_num-*prev(it) <= t){
                    return true;
                }
                if (next(it) != window.end() and *next(it)-curr_num <= t){
                    return true;
                }
            }
            
            return false;
        }
    };
    

    NOTE:

    • window.erase(window.lower_bound(nums[i-k-1]));window.erase(window.find(nums[i-k-1]));基本是一回事,find在multiset里面就随便找到一个就可以了

    相关文章

      网友评论

          本文标题:220. Contains Duplicate III (M)

          本文链接:https://www.haomeiwen.com/subject/hddqiktx.html