每日一题:存在重复元素II

地址

难度

简单

题目

给你一个整数数组nums和一个整数k,判断数组中是否存在两个 不同的索引i和j,满足nums[i] == nums[j] 且 abs(i-j) <= k。如果存在,返回true;否则,返回false 。

示例 1:

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

输出:true

示例 2:

输入:nums = [1,0,1,1], k = 1

输出:true

示例 3:

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

输出:false

提示:

* 1 <= nums.length <= 10^5
* -10^9 <= nums[i] <= 10^9
* 0 <= k <= 10^5

思路

  • 暴力破解

双重 for 循环。判断是否存在相同的值并且其索引的绝对值小于等于 K

时间复杂度 O(n^2),空间复杂度 O(1)。不过在 Leetcode 上执行的时候。提示超时时间限制

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] == nums[j] && Math.abs(i - j) <= k) {
                    return true;
                }
            }
        }
        return false;
    }
}
  • HashMap

在 hashMap 中有一个containsKey方法,即判断是否包含指定的键名。

利用 for 循环数组,发现有重复的数值,则将其索引和 hashMap 存储的索引相减,看其绝对值是否小于等于 K

时间复杂度 O(n),空间复杂度 O(n)。

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        HashMap<Integer,Integer> map =new HashMap<>();
        for(int i =0;i<nums.length;i++){
            if(map.containsKey(nums[i])){
                int x = map.get(nums[i]);
                if(Math.abs(x-i)<=k){
                    return true;
                }
            }
            map.put(nums[i],i);
        }
        return false;
    }
}
  • HashSet

维护一个哈希表,里面始终最多包含 k 个元素,当出现重复值时则说明在 k 距离内存在重复元素。每次遍历一个元素则将其加入哈希表中,如果哈希表的大小大于 k,则移除最前面的数字

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

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        HashSet<Integer> set =new HashSet<>();
        for(int i =0;i< nums.length;i++){
            if(set.contains(nums[i])){
                return true;
            }
            set.add(nums[i]);
            if(set.size() > k){
                set.remove(nums[i-k]);
            }
        }
        return false;
    }
}