🔍 LeetCode|存在重复元素(Contains Duplicate)学习笔记

13 阅读2分钟

一题两解,顺便搞懂 HashSet 的底层逻辑


一、题目描述(快速过)

给你一个整数数组 nums
只要数组中存在任意重复元素,就返回 true,否则返回 false

示例

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

输入:nums = [1,2,3,4]
输出:false

二、解题思路总览

这道题本身不难,但它非常适合考察你对 Java 集合的理解深度

我们用两种常见且实用的方法来解决:

  1. HashSet(推荐,最优解)
  2. 排序 + 相邻比较(不用额外集合)

三、方法一:HashSet(最推荐 ⭐)

核心思想

  • Set 的特点:不允许重复元素
  • 如果往 Set 里添加一个已经存在的元素,会失败

Java 实现代码

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int x : nums) {
            if (!set.add(x)) {
                return true;
            }
        }
        return false;
    }
}

关键点拆解(非常重要)

1️⃣ set.add(x) 返回值含义

set.add(x)
  • 如果 x 之前不存在 → 返回 true
  • 如果 x 已经存在 → 返回 false

所以:

if (!set.add(x)) {
    return true;
}

等价于:

“如果当前元素已经出现过,直接返回 true”


时间 & 空间复杂度

项目复杂度
时间复杂度O(n)
空间复杂度O(n)

为什么 HashSet 这么快?

  • 底层是 哈希表
  • 插入 / 查询平均时间复杂度都是 O(1)

📌 面试官常问:

为什么不用 List?
👉 因为 List 的 contains 是 O(n),整体会变成 O(n²)


四、方法二:排序 + 相邻比较

思路说明

如果数组是有序的:

  • 重复元素一定会相邻出现
  • 只需要遍历一遍,比较 nums[i]nums[i-1]

Java 实现代码

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == nums[i - 1]) {
                return true;
            }
        }
        return false;
    }
}

时间 & 空间复杂度

项目复杂度
时间复杂度O(n log n)
空间复杂度O(1)(忽略排序内部开销)

这种方法适合什么时候?

  • ❌ 不要求保留原数组顺序
  • ❌ 对性能要求没那么极致
  • ✅ 不想使用额外数据结构

五、两种方法对比总结

对比点HashSet排序
时间复杂度O(n) ⭐O(n log n)
空间复杂度O(n)O(1)
是否修改原数组
代码直观性⭐⭐⭐⭐⭐
面试推荐度⭐⭐⭐⭐⭐⭐⭐⭐

📌 结论一句话:

能用 HashSet 就用 HashSet,
排序法是“备用方案”。


六、这道题真正考察什么?

  • 是否理解 Set 的不重复特性
  • 是否知道 add() 的返回值含义
  • 是否能权衡 时间复杂度 vs 空间复杂度
  • 是否写出 简洁而有表达力的代码