• 220. Contains Duplicate III(核心:set数组有序/桶排序)


    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:
        //|i-j| <= k
        //|nums[i]-nums[j]| <= t
        //正常思路:O(N*k)超时
        //优化:1、O(N*logk).在 i--i+k中找是否在j使|nums[i]-nums[j]| <= t
        //如果nums[i]--nums[i+k]有序,即可找   nums[i]-t <= nums[j]  || nums[j] >= t+nums[i]
        //即在有序数组中查找 大于等于nums[i]-t的数 是否存在? 二分(logk)活着lower_boud函数
        //难点在于如何构造nums[i] -- nums[i+k]的有序数组? set
        /*
        lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
    
    在从小到大的排序数组中,
    
    lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
    
    upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
    
    
    STL的map、multimap、set、multiset都有三个比较特殊的函数,lower_bound、upper_bound、equal_range。
    
    
    iterator lower_bound (const value_type& val) const;
    
    iterator upper_bound (const value_type& val) const;
    
    pair<iterator,iterator> equal_range (const value_type& val) const;
     上面三个函数是相关联的,equal_range返回两个迭代器,第一个迭代器是lower_bound的返回值,第二个迭代器是upper_bound的返回值。(注意是使用相同val值调用的情况下。)
        */
        bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
            int n = nums.size();
            set<long> s;
            for(int i=0;i<n;i++){
                long cur = nums[i];
                //为何是 i>k 不是i>=k,因为这里是从后往前处理(这样就不会包含自己),每次遇到nums[i],看nums[i-k]--nums[i-1]
                //中nums[i]是否能够满足其中某一个的条件
                if(i > k) s.erase(nums[i-k-1]);
                //保持set长度k.容纳i-k-->i-1的元素
                 
                //i == k的时候正好是nums[i] 与 set中[i+1]--[k]的比较
                
                auto iter = s.lower_bound(cur-long(t));
                //iter值大于等于 cur-long(t) ,同时要小于等于 long(t)+cur
                if(iter != s.end() && *iter <= long(t)+cur) return true;
                //插入cur
                s.insert(cur);
            }
            return false;
        }
    };

    //桶排序:这个很经典    桶宽(t+1)

    class Solution {
    public:
        //桶排序:所有的数分桶,(t)为桶宽度范围。(t+1): 例如 t = 2, (0,1,2在桶0,3,4,5在桶1 ...
        //获取nums[i]在哪个桶: 桶id从0开始,num小于0的话,例如  -1 / 2 == 0不行。
        long getId(long num,long t) {
            return num < 0 ? (num+1)/(t+1)-1 : num/(t+1);
        }
        long Abs(long a) {
            if(a < 0) return -a;
            return a;
        } 
        //num -- num+t 会在一个桶内,如果 k哥元素范围内必有同范围内的,返回true
        bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
            //key 为ID ,value为nums[i]。至多一个value,否则就返回了
            map<long,long> m;
            int n = nums.size();
            for(int i=0;i<n;i++){
                long cur = nums[i];
                long id = getId(cur,t);
                //同一个桶内有元素
                if(m.find(id) != m.end()) return true;
                //相邻桶内也有,相邻桶也必然至多一个元素,否则就满足条件了
                if(m.find(id-1) != m.end() && Abs(cur-m[id-1]) <= t){
                    return true;
                }
                //相邻桶内也有
                if(m.find(id+1) != m.end() && Abs(cur-m[id+1]) <= t){
                    return true;
                }
                //存入cur
                m[id] = cur;
                //删除超过的:为啥是i>=k , 这里保证桶里最多k-1个。
                if(i >= k) {
                    auto iter = m.find(getId(nums[i-k],t));
                    m.erase(iter);
                }
            }
            return false;
        }
    };
  • 相关阅读:
    用wifi调试android程序
    【翻译】Ext JS 4.1的性能
    index range scan,index fast full scan,index skip scan发生的条件
    柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系1 柱状图
    柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系3 柱状图与cursor_sharing
    JNI开发入门
    索引的Clustering Factor
    索引选择性
    列定义允许null,可能导致Index Hint提升不走索引
    柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系2 绑定变量与柱状图
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/14092268.html
Copyright © 2020-2023  润新知