题目

给你一个整数数组 nums 。

如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 1:

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

输出:true

解释:

元素 1 在下标 0 和 3 出现。

示例 2:

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

输出:false

解释:

所有元素都不同。

示例 3:

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

输出:true

提示:

1 <= nums.length <= 10^5

-10^9 <= nums[i] <= 10^9

整体思路

这个系列的题目是一样的解法。

主要有几个思路:

1)HashMap 计数,这个应该很容易想到

2)利用 HashSet 去重,比如这里如果最后的 size 小于整体,则认为是满足。

3)排序 然后如果 nums[i] == nums[i+1],则证明存在重复

4)位运算

个人其实非常喜欢前面 3 种解法,第三种应该是位运算之外最优的解法。

实用性很强,而且容易想到。

v1-HashMap

思路

HashMap 计数,这个应该很容易想到

实现

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for(int num : nums){
            countMap.put(num, countMap.getOrDefault(num, 0) +1);
        }

        for(Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            if(entry.getValue() != 1) {
                return true;
            }
        }

        return false;
    }
}

效果

31ms 5.06%

效果比较差。

v2-set 去重

思路

通过 set,如果最后的 size 小于原始数组,则满足存在重复。

实现

public boolean containsDuplicate(int[] nums) {
    Set<Integer> set = new HashSet<>();
    for(int num : nums){
        set.add(num);
    }
    return set.size() < nums.length;
}

效果

18ms 18.50%

有所提升

v3-set 改进

思路

其实我们不需要等元素全部遍历一遍才返回。

我们判断包含后就直接返回。

代码

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

效果

11ms 76.07%

效果还是不错的。

v4-排序

思路

数字排序,重复时,则下一个元素和当前的元素相同。

实现

class Solution {
     public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);

        for(int i = 0; i < nums.length-1; i++){
            if(nums[i] == nums[i+1]) {
                return true;
            }
        }

        return false;
    }
}

效果

19ms 35.43%

小结

其实也是不错的解法。

v5-位运算

解题思路

小结