前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【LeetCode每日一题】220. 存在重复元素 III

【LeetCode每日一题】220. 存在重复元素 III

作者头像
公众号guangcity
发布2021-04-22 11:44:38
2640
发布2021-04-22 11:44:38
举报
文章被收录于专栏:光城(guangcity)

【LeetCode每日一题】220. 存在重复元素 III

今日题目220题,每日一题微信交流群可以点击右下角:合作转载->联系我,备注:刷题,拉你入群。

题目:

给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。

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

示例 1:

代码语言:javascript
复制
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true

题解:

本题可以基于滑动窗口,可以采用桶、map、set、multiset等数据结构解决这道题目。

注意处理的时候加减操作会越界,需要转为long long处理。

滑动窗口+multiset

维护长度为k+1元素的滑动窗口,窗口内元素从左到右插入,并查询之前是否存在满足条件的元素,查找到了就返回true,否则继续移动窗口即可。

代码语言:javascript
复制
class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        multiset<long long> s;
        int i = 0, j = 0, n = nums.size();
        while (j < n) {
            while (j < n && j - i <= k) {
                // [nums[i] - k, nums[i] + k]
                auto iter = s.lower_bound((long long)nums[j] - t);
                if (iter != s.end() && *iter <= (long long)nums[j] + t) return true;
                s.insert(nums[j++]);
            }
            s.erase(nums[i++]);
        }
        return false;
    }
};

滑动窗口+桶

同上述方法维护滑动窗口,区别在于元素处理,这里采用map记录每个桶对应的元素是谁,如果已经有这个桶id了,那么就返回true,因为再次出现的元素两个一定满足<=t,而由于也在窗口内,所以满足条件直接返回true,同时还可以在周边桶会满足条件,分别是+1与-1桶的id,去检查即可。

桶id计算方法是:假设现在数据范围是[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],t=3,那么我们需要满足[0,1,2,3]均在index=0桶,[4,5,6,7]在index=1桶,依次类推。

那如果数据范围携带负数,例如:[-7,-6,-5,-4,-3,-2,-1,0,1,2],t=3,我们则需要[-4,-3,-2,-1]为index=-1桶,依次类推,而按照正数的计算num/(t+1)得到的0桶的范围是[-3,-2,-1,0],因此我们要得到-1桶,需要对负数右移一位这样就变成了[-3,-2,01,0]这样数据,此时计算式:(num+1)/(t+1),此时的桶index=0,我们需要把得到-1,再减去1,便是:(num+1)/(t+1) - 1。

代码语言:javascript
复制
class Solution {
public:
    long long w;
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        // k index
        // t value
        int n = nums.size();
        if (n == 0) return false;

        map<long long, long long> m; // id : value
        w = (long long)t + 1;
        int i = 0, j = 0;
        while (j < n) {
            while (j < n && j - i <= k) {
                int id = getBucketId(nums[j]);
                if (m.count(id)) return true;
                if (m.count(id - 1) && abs(m[id - 1] - nums[j]) <= t) return true;
                if (m.count(id + 1) && abs(m[id + 1] - nums[j]) <= t) return true;
                m[id] = nums[j++];
            }
            // j -i > k
            m.erase(getBucketId(nums[i++]));
        }
        return false;
    }

    int getBucketId(int num) {
        if (num >= 0) return num / w;
        else return (num + 1) / w - 1; // 向右平移一个单位得到的桶index 左移一个单位
    }
};

本节完~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【LeetCode每日一题】220. 存在重复元素 III
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档