题目
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.
我的解法(超时)
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null)
return false;
// 距离dis从1到k
for(int dis = 1; dis <= k; dis++)
//遍历数组,依次比较距离为dis的元素
for(int i = 0; i <= nums.length - dis; i++){
if(i + dis <= nums.length - 1 && nums[i] == nums[i + dis])
return true;
}
return false;
}
}
我的解法(改进后AC)
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null)
return false;
HashMap<Integer, ArrayList<Integer>> map = new HashMap<>();
for(int i = 0; i < nums.length; i ++){
// 若此数字还没出现过,则map中加入此数值及其位置索引数组
if(!map.containsKey(nums[i])){
ArrayList<Integer> list = new ArrayList<>();
list.add(i);
map.put(nums[i], list);
}
else{
// 出现过,则判断是否有满足条件的情况
for(int index : map.get(nums[i]))
if(i - index <= k)
return true;
map.get(nums[i]).add(i);
}
}
return false;
}
}
算法分析:存在冗余,因为没有想到“
索引是逐渐递增的,只要比较同一数字在数组的前后位置索引即可,如果这个不满足,之前的肯定也不满足”,这样,就不用使用ArrayList结构存储所有的位置了。
我的解法(按答案优化思路改进后)
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null)
return false;
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i ++){
// 若此数字还没出现过,则map中加入此数值的索引
if(!map.containsKey(nums[i]))
map.put(nums[i], i);
else{
// 比较同一num本次索引和前一次索引的距离
if(i - map.put(nums[i], i) <= k)
return true;
}
}
return false;
}
}
算法分析:时间空间复杂度都是O(n),因为需要存储每个num对应位置的索引。
答案解法(优化解法)
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null)
return false;
// 用长度为k + 1的窗口(首尾距离为k)滑动存储数组元素
HashSet<Integer> set = new HashSet<>();
for(int i = 0; i < nums.length; i ++){
// 判断窗口长度是否为K + 1了
if(i >= k + 1)
set.remove(nums[i - k - 1]);
// 通过判断是否添加成功,来判断窗口里是否还有重复元素(相等元素)
if(!set.add(nums[i]))
return true;
}
return false;
}
}
算法分析:遍历一遍,时间复杂度为O(n),空间复杂度为O(k),只需存储长度为k的窗口内的元素。