「力扣」第 220 题:220. 存在重复元素 III(滑动窗口)

题解地址:https://leetcode-cn.com/problems/contains-duplicate-iii/solution/hua-dong-chuang-kou-er-fen-sou-suo-shu-zhao-shang-/

方法一:暴力解法

枚举所有长度小于等于 k + 1 的“下标对()”,只要发现 nums[i] - nums[j] 的绝对值小于 t ,就返回 true

Java 代码:

public class Solution {

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        int len = nums.length;
        long a;
        long b;

        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j < len && j <= i + k; j++) {
                a = nums[i];
                b = nums[j];
                if (Math.abs(a - b) <= t) {
                    return true;
                }
            }
        }
        return false;
    }
}

复杂度分析

  • 时间复杂度: O ( N 2 ) O(N^2) ,这里数组的长度为 N N ,枚举可能的数对 ( i , j ) (i, j)
  • 空间复杂度: O ( 1 ) O(1)

方法二:滑动窗口(以空间换时间)

题目意思翻译一下:在数组 nums[i] 中,在任意区间 [i, i + k] 里是否存在两个数的绝对值小于等于 t,即 n u m s [ i ] n u m s [ j ] < = t |nums[i] - nums[j] | <= t

等价于 n u m s [ i ] n u m s [ j ] < = t nums[i] - nums[j] <= t 并且 n u m s [ i ] n u m s [ j ] > = t nums[i] - nums[j] >= -t

n u m s [ i ] < = t + n u m s [ j ] nums[i] <= t + nums[j] 并且 n u m s [ i ] > = n u m s [ j ] t nums[i] >= nums[j] - t

Java 代码:

import java.util.TreeSet;

public class Solution {

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        // 滑动窗口结合查找表,此时滑动窗口即为查找表本身(控制查找表的大小即可控制窗口大小)
        TreeSet<Long> set = new TreeSet<>();
        for (int i = 0; i < nums.length; i++) {
            // 边添加边查找
            // 查找表中是否有大于等于 nums[i] - t 且小于等于 nums[i] + t 的值
            Long ceiling = set.ceiling((long) nums[i] - (long) t);
            if (ceiling != null && ceiling <= ((long) nums[i] + (long) t)) {
                return true;
            }
            // 添加后,控制查找表(窗口)大小,移除窗口最左边元素
            set.add((long) nums[i]);
            if (set.size() == k + 1) {
                set.remove((long) nums[i - k]);
            }
        }
        return false;
    }
}

另一种写法:在一开始就把多余的元素删除。

Java 代码:

import java.util.TreeSet;

public class Solution11 {

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        int len = nums.length;
        // 特判
        if (len == 0 || k <= 0 || t < 0) {
            return false;
        }

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

        for (int i = 0; i < len; i++) {
            if (i > k) {
                set.remove((long) nums[i - k - 1]);
            }

            Long ceiling = set.ceiling((long) nums[i] - (long) t);
            if (ceiling != null && ceiling <= (long) nums[i] + (long) t) {
                return true;
            }

            set.add((long) nums[i]);
        }
        return false;
    }
}

复杂度分析

  • 时间复杂度: O ( N log K ) O(N\log K) ,遍历数组使用 O ( N ) O(N) ,在遍历的同时向二叉搜索树中插入元素和移除元素的时间复杂度是 O ( log K ) O(\log K)
  • 空间复杂度: O ( 1 ) O(1)
发布了446 篇原创文章 · 获赞 334 · 访问量 124万+

猜你喜欢

转载自blog.csdn.net/lw_power/article/details/104323053
今日推荐