[leetcode] 220. Contains Duplicate III

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

分析

题目的意思是:给定一个整数数组,两个数差距最多为t,两数的间隔最大为k。

  • 这里需要两个指针i和j,刚开始i和j都指向0,然后i开始向右走遍历数组,如果i和j之差大于k,且m中有nums[j],则删除并j加一。这样保证了m中所有的数的下标之差都不大于k.
  • 我们用map数据结构的lower_bound()函数来找一个特定范围,就是大于或等于nums[i] - t的地方,所有小于这个阈值的数和nums[i]的差的绝对值会大于t.
  • 然后检测后面的所有的数字,如果数的差的绝对值小于等于t,则返回true.

C++实现

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        map<long long,int> m;
        int j=0;
        for(int i=0;i<nums.size();i++){
            if(i-j>k) m.erase(nums[j++]);
            auto a=m.lower_bound((long long)nums[i]-t);
            if(a!=m.end()&&abs(a->first-nums[i])<=t){
                return true;
            }
            m[nums[i]]=i;
        }
        return false;
    }
};

Python实现

这道题用滑动窗口效率会很低,因为t和k可以很大,另一种思路就是分桶。

class Solution:

    def get_bucket_id(self,x, w):
        return x//w

    def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
        if t<0:
            return False

        buckets = {}
        width = t+1
        for i in range(len(nums)):
            bucket_id = self.get_bucket_id(nums[i],width)
            for j in range(bucket_id-1,bucket_id+2):
                if j in buckets and abs(buckets[j]-nums[i])<=t:
                    return True
            buckets[bucket_id]=nums[i]
            if i>=k:
                del buckets[self.get_bucket_id(nums[i-k],width)]
        return False

参考文献

[LeetCode] Contains Duplicate III 包含重复值之三

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农民小飞侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值