题目:判断数据中是否有两个数相同且两个数的下标差不超过K,若有,返回True,否则返回False。
来源:ProblemLink
思路1:暴力遍历
遍历数组,对于数组的每个数都朝后遍历K个,时间复杂度为O(Kn)。
思路2:使用HashMap
使用HashMap维护一个大小为K的窗口,首先将数组前K个数放入窗口中,判断是否有相同,若有,则结果为True。若没有,则向后滑动窗口,即移除窗口最前面一个数,将数组下一个数放入窗口。
public boolean containsNearbyDuplicate(int[] nums, int k) {
int nums_len=nums.length;
if (nums_len<2)
return false;
Map<Integer,Integer> m=new HashMap<Integer,Integer>();
for(int i=0;i<k&&i<nums_len;i++){
if (m.values().contains(nums[i]))
return true;
m.put(i, nums[i]);
}
if (nums_len>=k) return false;
for(int j=k;j<nums_len;j++){
if (m.values().contains(nums[j]))
return true;
m.remove(j-k);
m.put(j, nums[j]);
}
return false;
}
}
但代码中用到了m.remove,HashMap中删除时会遍历整个Map找到键值为给定值的删除,时间复杂度仍然为O(kn)。
思路3:HashMap中put方法时间复杂度为O(1),所以尝试将remove操作转化为put。即HashMap中键为数组中数据,值为一个布尔值,true表示该数据在滑动窗口内,false表示该数据不在滑动窗口内。于是,将数据从滑动窗口内移除的操作m.remove(j-k)改成put(nums[j-k],false)。
public boolean containsNearbyDuplicate(int[] nums, int k) {
k=k+1;
int nums_len=nums.length;
if (nums_len<2)
return false;
HashMap<Integer,Boolean> m=new HashMap<Integer,Boolean>();
for(int i=0;i<k&&i<nums_len;i++){
if (m.keySet().contains(nums[i]))
return true;
m.put(nums[i], true);
}
if (nums_len<=k) return false;
for(int j=k;j<nums_len;j++){
m.put(nums[j-k],false);
if (m.keySet().contains(nums[j])&& m.get(nums[j])==true)
return true;
m.put(nums[j],true);
}
return false;
}