16.存在重复元素2
一、题目
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],
并且 i 和 j 的差的 绝对值 至多为 k。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate-ii
二、示例
示例①
输入: nums = [1,2,3,1], k = 3
输出: true
示例②
输入: nums = [1,0,1,1], k = 1
输出: true
三、代码实现
方法一: 线性搜索
public static boolean containsNearbyDuplicate(int[] nums, int k) {
for (int i = 0; i < nums.length; ++i) {
for (int j = Math.max(i - k, 0); j < i; ++j) {
if (nums[i] == nums[j]) return true;
}
}
return false;
}
由Math.max(i - k)j的起点从而限制for循环的遍历范围
方法二:二叉搜索树
public static boolean containsNearByDuplicateByBinarySearchTree(int[] nums,int k){
Set<Integer> set = new TreeSet<>();
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;
}
若树的size大于k,则树移除[i-k],也就是最先进入的那个
方法三: 散列表(哈希表)
public static boolean containsNearByDuplicateByHashTable(int[] nums,int k){
Set<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;
}
跟二叉搜索树差不多,主要注意HashSet与TreeSet的区别
方法四:HashMap
public static boolean containsNearbyDuplicateByHashMap(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
Integer index = map.get(nums[i]);
if (index == null) {
map.put(nums[i], i);
} else if (i - index <= k) {
return true;
} else {
map.put(nums[i], i);
}
}
return false;
}
map.get(nums[i])是核心,就是说有没有nums[i]这个key,有就把它的value也就是索引拿出来,没有就由后面的判断语句判断是否为null,是直接添加进map
四、复杂度分析
线性搜索
- 时间复杂度:O(nmin(k,n))
- 空间复杂度:O(1)
二叉搜索树
- 时间复杂度:O(nlog(min(k,n)))
- 空间复杂度:O(min(n,k))
散列表(哈希表)
- 时间复杂度:O(n)
- 空间复杂度:O*(min(n,k))