leetcode 桶排序用法例题

1 题目

在整数数组 nums 中,是否存在两个下标 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值小于等于 t ,且满足 i 和 j 的差的绝对值也小于等于 ķ 。

如果存在则返回 true,不存在返回 false。

2 答案

https://leetcode-cn.com/problems/contains-duplicate-iii/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-46/参考

class Solution {
public:
    int getid(int x, int w){
        if(x>=0){
            return x/w;
        }
        else{
            return (x+1)/w -1;
        }
    }
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        unordered_map<int,int> tmap;
        int len = nums.size();
        long long t_size = (long long)t+1;
        for(int i=0;i<len;++i){
            if(i>k){
                tmap.erase(getid(nums[i-k-1],t_size));
            }

            int id = getid(nums[i],t_size);
            if(tmap.find(id) != tmap.end()){
                return true;
            }
            else if(tmap.find(id+1) != tmap.end() && abs((long long)tmap[id+1]-(long long)nums[i]) < t_size){
                return true;
            }
            else if(tmap.find(id-1) != tmap.end() && abs((long long)tmap[id-1]-(long long)nums[i]) < t_size){
                return true;
            }

            tmap[id] = nums[i];
        }
        return false;
    }
};

3 整体思路

(1)建立桶

设定桶的大小t_size = t+1,表示桶内部的元素之差最大是t。每个桶都有一个标签id,nums的元素可以通过计算确定每个元素属于哪一个桶。
例如:
nums[0,1,2,3,4,5,6,7,8,9]
t_size = 4
id = nums[i]/t_size
桶 0 [0,1,2,3]
桶 1 [4,5,6,7]
桶 2 [8,9]
这样每一个元素只与自己所在桶,上一个桶,下一个桶里边的元素之差 小于等于 t。另外每个桶里边可以只包含一个元素。还有一件值得注意的事,这个问题和桶排序的不同之处在于每次我们的桶里只需要包含最多一个元素就可以了,因为如果任意一个桶中包含了两个元素,那么这也就是意味着这两个元素是 足够接近的 了,这时候我们就直接得到答案了(抄LeetCode题解)。

(2)桶id确定

nums[],内部元素当>=0时,可以直接根据size计算
nums:0, 1,2, 3,4, 5,6, 7,8,9
id: 0, 0, 0,0,1, 1,1,1,2, 2
当<0时,如果还按照原来的办法计算
nums: -1,-2, -3,-4, -5,-6, -7,-8,-9
id: 0, 0, 0,-1, -1,-1,-1,-2, -2
0被用了两次,而且数目还不对
(x+1)/w -1;
nums: 0, -1,-2, -3,-4, -5,-6, -7,-8,
id: -1, -1,-1,-1,-2, -2,-2,-2,-3
这样就能保证,每个元素对应的桶是正确的。

    int getid(int x, int w){
        if(x>=0){
            return x/w;
        }
        else{
            return (x+1)/w -1;
        }
    }

(3)判断结果

int id = getid(nums[i],t_size);
if(tmap.find(id) != tmap.end()){ //如果当前元素所属桶里边已经有元素了,那差肯定<=t
    return true;
}
else if(tmap.find(id+1) != tmap.end() && abs((long long)tmap[id+1]-(long long)nums[i]) < t_size){   //如果当前元素所属桶内没有元素,那么在前后两个桶内继续判断
    return true;
}
else if(tmap.find(id-1) != tmap.end() && abs((long long)tmap[id-1]-(long long)nums[i]) < t_size){
    return true;
}
// 如果以上三个情况都不是,那么就新建一个桶,装当前元素
tmap[id] = nums[i];

(4)限制桶

例如:
nums[1,5,9,1,17] t=3,k=2
i = 0, nums[0] = 1, 桶id = 0
i = 1, nums[1] = 5, 桶id = 1
i = 2, nums[2] = 9, 桶id = 2 此时,i-0 <= 2
i = 3, nums[3] = 1, 桶id = 0 此时,i-0 > 2,我们应该将桶id=0,删去,保证每次判断的元素符合<k
i = 4, nums[4] = 17, 桶id = 4

if(i>k){
    tmap.erase(getid(nums[i-k-1],t_size));  //i-k-1,将不在 i-j<k范围内的元素,剔除
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值