Contains Duplicate I
Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.
集合法
复杂度
时间 O(N) 空间 O(N)
思路
用一个集合记录之前遇到过的数字,如果新的数字已经在集合中出现过了,则说明有重复。
代码
public class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < nums.length; i++){
if(set.contains(nums[i])) return true;
set.add(nums[i]);
}
return false;
}
}
Contains Duplicate II
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k.
集合法
复杂度
时间 O(N) 空间 O(K)
思路
同样使用集合,但这次我们要维护集合的大小不超过k,相当于是记录一个宽度为k的窗口中出现过的数字。
代码
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Set<Integer> set = new HashSet<Integer>();
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;
}
}
Contains Duplicate III
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.
二叉搜索树
复杂度
时间 O(NlogK) 空间 O(K)
思路
要求判断之前是否存在差值小于t的数字,我们需要知道在当前数字x两边的数字,即最大的小于x的数字和最小的大于x的数字。二叉搜索树有也有这样的性质,它的左子树的最右节点是最大的较小值,右子树的最左节点是最小的较大值。这里我们用TreeSet这个类,它实现了红黑树,并有集合的性质,非常适合这题。我们同样也是维护一个大小为k的TreeSet,多余k个元素时把最早加入的给删除。用ceiling()和floor()可以找到最小的较大值和最大的较小值。
代码
public class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
TreeSet<Integer> set = new TreeSet<Integer>();
for(int i = 0; i < nums.length; i++){
int x = nums[i];
// 最大的小于x的数字
if(set.ceiling(x) != null && set.ceiling(x) <= t + x) return true;
// 最小的大于x的数字
if(set.floor(x) != null && x <= t + set.floor(x)) return true;
set.add(x);
if(set.size()>k) set.remove(nums[i-k]);
}
return false;
}
}