题目
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.
解法
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums.length == 0||nums.length == 1) return false;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int num:nums){
if(num < min) min = num;
if(num > max) max = num;
}
Integer[] flag = new Integer[max - min + 1];
for(int i = 0;i < flag.length;i++){
flag[i] = null;
}
for(int i = 0;i < nums.length;i++){
if(flag[nums[i]-min]!=null){
if((i-flag[nums[i]-min]) <= k) return true;
}else{
flag[nums[i]-min] = i;
}
}
return false;
}
}
思路
最容易想到的就是排个序,然后便利看前后是否有重复。
找到最大值最小值,以该差值建立一个新的数组用于标记,将原数组的数值作为索引链到新数组上,如果有重复则会重复链到同一个位置。但是原数组数值可能是负数怎么办?就用数值减去最小值,保证了正数。但它是相当于用空间复杂度代替时间复杂度。建议用set集合的方式。
这种思路还存在着两个问题,你用max,min去创建数组,万一原数组是[-248176541,248176541]这种形式呢,不仅有非常大的空间浪费,而且当max-min超过int范围怎么办
这种思路还存在着两个问题,你用max,min去创建数组,万一原数组是[-248176541,248176541]这种形式呢,不仅有非常大的空间浪费,而且当max-min超过int范围怎么办
题目二
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
absolute
difference between
i
and
j
is at most
k
.
解法
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < nums.length; i++){
if(i > k) set.remove(nums[i-k-1]);
if(!set.add(nums[i])) return true;
}
思路
一开始想用map来记录每个值和他对应的索引,当containskey以后,比较两个索引的差值,猛一看觉得没什么问题,但是你是从头到尾往map里面放的话,第一个进去了,下一次跟它重复的如果离得很远被跳过,但是之后每一个重复的数字都是在跟他们第一次出现的位置比,而不是跟他们上一次出现的位置比,所以还不如直接用set,只把k长的数据放进去,相当于每个数只跟他们前边k个数范围进行判断是否contains
也可以在第一题的基础上,第一题是对一个数组判定是否存在重复。第二题相当于一个数组的k窗口大小判定是否重复,遍历一遍窗口大小的子数组,分别用第一题进行判定
错误代码
Map<Integer,Integer> map = new HashMap();
for(int i = 0;i < nums.length;i++){
if(map.containsKey(nums[i])){
if((i - map.get(nums[i])) <= k) return true;
}else{
map.put(nums[i],i);
}
}
return false;