【力扣】存在重复元素系列

【力扣】存在重复元素系列

Leetcode 0217 存在重复元素

题目描述:Leetcode 0217 存在重复元素

在这里插入图片描述

分析

  • 本题的考点:哈希表

  • 依次遍历每个元素,判断当前遍历的元素是否在哈希表中存在,如果存在,说明存在重复元素,否则将该元素插入哈希表中。

  • 如果遍历结束都没有发现重复元素,返回false即可。

代码

  • C++
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> S;
        for (int x : nums) {
            if (S.count(x)) return true;
            S.insert(x);
        }
        return false;
    }
};
  • Java
class Solution {
    public boolean containsDuplicate(int[] nums) {
        HashSet<Integer> S = new HashSet<>();
        for (int x : nums) {
            if (S.contains(x)) return true;
            S.add(x);
        }
        return false;
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n为数组长度。

  • 空间复杂度: O ( n ) O(n) O(n)

Leetcode 0219 存在重复元素 II

题目描述:Leetcode 0219 存在重复元素 II

在这里插入图片描述

分析

  • 本题的考点:哈希表

  • 不同于Leetcode 0217 存在重复元素,LC217使用的是set,本题使用map记录每个元素对应的下标,如果存在重复元素,判断当前考察元素x的下标和hash[x]之间的距离是否小于等于k即可。

代码

  • C++
class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int, int> hash;  // (数据, 数据在数组中对应的下标)
        for (int i = 0; i < nums.size(); i++) {
            int x = nums[i];
            if (hash.count(x) && i - hash[x] <= k) return true;
            hash[x] = i;
        }
        return false;
    }
};
  • Java
class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        HashMap<Integer, Integer> hash = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int x = nums[i];
            if (hash.containsKey(x) && i - hash.get(x) <= k) return true;
            hash.put(x, i);
        }
        return false;
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n为数组长度。

  • 空间复杂度: O ( n ) O(n) O(n)

Leetcode 0220 存在重复元素 III

题目描述:Leetcode 0220 存在重复元素 III

在这里插入图片描述

分析

  • 本题的考点:哈希表

  • 若存在i、j,且j < i,有 a b s ( n u m s [ i ] − n u m s [ j ] ) ≤ t abs(nums[i] - nums[j]) \le t abs(nums[i]nums[j])t,则有 − t ≤ n u m s [ j ] − n u m s [ i ] ≤ t -t \le nums[j] - nums[i] \le t tnums[j]nums[i]t,则有: n u m s [ i ] − t ≤ n u m s [ j ] ≤ n u m s [ i ] + t nums[i]-t \le nums[j] \le nums[i] + t nums[i]tnums[j]nums[i]+t

  • 下面步骤中的x就是这里的nums[j]

  • 本题分为如下三步:

    (1)使用 C++ 提供的 multiset 来记录 [i-k, i-1] 中连续 k 个数字。

    (2)对于当前的 num[i],用 multiset 中的 lower_bound 找到 multiset 中第一个大于等于 nums[i] - t 的数字。

    (3)如果存在该数字 x,且 x <= nums[i] + t,则返回 true

  • 对于Java而言,可以使用TreeSet,使用ceiling(x)返回大于等于x的第一个数。

代码

  • C++
class Solution {
public:
    typedef long long LL;

    bool containsNearbyAlmostDuplicate(vector<int> &nums, int k, int t) {

        multiset<LL> S;
        for (int i = 0; i < nums.size(); i++) {
            LL x = (LL) nums[i] - t;
            LL y = (LL) nums[i] + t;
            if (S.lower_bound(x) != S.end() && *S.lower_bound(x) <= y) return true;
            S.insert(nums[i]);
            if (S.size() == k + 1) S.erase(S.find(nums[i - k]));
        }
        return false;
    }
};
  • Java
class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {

        TreeSet<Long> S = new TreeSet<Long>();
        for (int i = 0; i < nums.length; i++) {
            long num1 = (long) nums[i] - t;
            long num2 = (long) nums[i] + t;
            if (S.ceiling(num1) != null && S.ceiling(num1) <= num2) return true;
            S.add((long) nums[i]);
            if (S.size() == k + 1) S.remove((long) nums[i - k]);  // 保证滑动窗口长度始终为k,有k+1个元素
        }
        return false;
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n为数组长度。

  • 空间复杂度: O ( k ) O(k) O(k)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值