220 Contains Duplicate III

本文介绍了一种算法,用于判断在给定的整数数组中是否存在两个不同索引i和j,使得它们之间的绝对差小于等于t,同时i和j之间的距离小于等于k。通过使用TreeSet作为滑动窗口,该算法在O(NlogK)的时间复杂度内解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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


解法思路(一)

  • 题目其实限定了 2 个条件:
    • 在一定范围内找;
    • 找和标定元素的绝对差(absolute difference)小于等于 t 的;
  • 在游标 i 前进的过程中,不满足条件的元素就被装入查找表
  • 不满足条件的元素是:nums[i] 在其后的窗口中,没有找到与 nums[i] 之间的绝对差小于等于 t 的,那么 nums[i] 就成了不满足条件的元素,要进入滑动窗口;
  • 查找表中能装的元素最多为 k + 1 个,查找表作为滑动窗口的容器,当其中的元素个数到达 k + 1 时要把滑动窗口的长度维护在 k
  • nums[i] 之间的绝对差等于 t 的元素分别表示为:nums[i] - tnums[i] + t
  • 在滑动窗口(查找表)中找到大于等于 nums[i] - t 的且小于等于 nums[i] + t 的元素,就成功了,否则,如果游标 i 都走完了整个数组没有满足这个条件的,则失败了;
  • 由于查找表中的元素涉及到大小的比较,所以 HashSet 就不能用了,要用 TreeSet 了,伴随而来的代价查找的时间复杂度从 O(1) 降为 O(logK);
  • 在哈希表中找大于等于某个值用方法: E ceiling(E e)

解法实现(一)

时间复杂度
  • O(NlogK);
空间复杂度
  • O(K);
关键字

查找表 TreeSet 整型溢出 绝对差 ceiling

实现细节
  • 如果 num[i] 已经是整型的最大值了,如果给出的绝对差也是整型的最大值,那么计算 num[i] 右边的元素 nums[i] + t 就会发生整型越界,这时,要把参加运算的所有整型强转成 long 型,故 TreeSet 中存储泛型要定义成 Long;
package leetcode._220;

import java.util.TreeSet;

public class Solution220_1 {

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {

        TreeSet<Long> windowK = new TreeSet<>();

        for (int i = 0; i < nums.length; i++) {
            if (windowK.ceiling((long)nums[i] - (long)t) != null
                    && windowK.ceiling((long)nums[i] - (long)t) <= (long)nums[i] + (long)t) {
                return true;
            }

            windowK.add((long)nums[i]);
            if (windowK.size() == k + 1) {
                windowK.remove((long)nums[i - k]);
            }
        }

        return false;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值