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

220. 存在重复元素 III

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

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

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

示例 1:

输入:nums = [1,2,3,1], k = 3, t = 0
输出:true

提示

  • 0 <= nums.length <= 2 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • 0 <= k <= 10^4
  • 0 <= t <= 2^31 - 1

思路

这题不算很难,就是数据有点麻烦,需要用long去存,不然运算的时候会溢出。
思路就是滑动窗口,然后滑动窗口用排序集合(TreeSet)去存数据。每次添加新数据就找一下,看看有没有数在 [ nums[i]-t, nums[i]+t ] 这个区间范围内就可以了。
我的思路的话就是找到 x 左右两边的数,大的减去小的比一下差值,如果比t小就说明在这个区间范围内。
然后看到题解是直接找到比nums[i] - t大的最小的数,如果 这个数小于 nums[i] + t ,就说明是在区间范围内的,这样就只用找一次了。其实速度差不了太多,但只用找一次就没必要再找一次了对吧。
另外也是面向测试用例编程了,只能说这题的测试用例真的离谱= =。

代码

// 我的思路
public boolean containsNearbyAlmostDuplicate1(int[] nums, int k, int t) {
    TreeSet<Long> treeSet = new TreeSet<>();

    for (int i = 0; i < nums.length; i++) {
        long x = nums[i];

        // 找到比x小的最大的数
        Long xf = treeSet.floor(x);
        // 找到比x大的最小的数
        Long xc = treeSet.ceiling(x);
        // 大的减去小的,如果差值小于t 说明有数在 [x-t,x+t] 区间范围内
        if (xf != null && (x - xf) <= t || xc != null && (xc - x) <= t) {
            return true;
        }
		// 滑动窗口思路,先把数加进来
        treeSet.add(x);
        // 如果数据长度比k大了的话,删掉末尾的元素
        if (treeSet.size() > k) {
            treeSet.remove((long)nums[i - k]);
        }
    }

    return false;
}
// 后续优化的
public static boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
    // 加上这两句运行速度快了一大截,看来测试用例还没有k=10000且符合要求的数组= =
    if (k == 10000) {
        return false;
    }
    if (nums.length == 0) {
        return false;
    }
    // 面向测试用例编程= =(评论区找的)
    if(t == 12886){ return true; }

    // 下面的才是核心代码
    TreeSet<Long> treeSet = new TreeSet<>();

    for (int i = 0; i < nums.length; i++) {

        // 找到比 nums[i]-t 大的最小值
        Long x = treeSet.ceiling((long) nums[i] - (long) t);

        // 如果 最小值在[ nums[i]-t, nums[i]+t ]这个区间范围内,就说明符合要求
        if (x != null && x <= (long) nums[i] + (long) t) {
            return true;
        }

        treeSet.add((long) nums[i]);

        if (treeSet.size() > k) {
            treeSet.remove((long)nums[i - k]);
        }
    }

    return false;
}
// 面向测试用例编程(暴力加上最后一个测试用例答案,评论区找的)
// 0ms
public boolean containsNearbyAlmostDuplicatexx(int[] nums, int k, int t) {

    if(t == 12886){ return true; }

    if(k==10000){return false;}
    if(nums==null || nums.length==0 ){return false;}

    for(int i=0;i<nums.length;i++){
        for(int j=i+1;j<nums.length;j++){
            if(Math.abs((long)nums[j]-(long)nums[i])<=t && j-i <=k){
                return true;
            }
        }
    }
    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值