Given an array of integers and an integer k, return true if and only if 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.
Java Solution 1 – HashMap
public boolean containsNearbyDuplicate(int[] nums, int k) { HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for(int i=0; i<nums.length; i++){ if(map.containsKey(nums[i])){ int pre = map.get(nums[i]); if(i-pre<=k) return true; } map.put(nums[i], i); } return false; } |
Java Solution 2 – HashSet
public boolean containsNearbyDuplicate(int[] nums, int k) { if(nums==null || nums.length<2 || k==0) return false; int i=0; HashSet<Integer> set = new HashSet<Integer>(); for(int j=0; j<nums.length; j++){ if(!set.add(nums[j])){ return true; } if(set.size()>=k+1){ set.remove(nums[i++]); } } return false; } |
A bit simpler solution – just one pointer `i`:
boolean containsDuplicates(int[] nums, int k)
{
if (nums == null || nums.length <= 1 || k <= 0) return false;
HashSet exists = new HashSet(k); // TODO: take into control load factor.
for (int i = 0 ; i k)
{
exists.remove(nums[i-k]);
}
}
return false;
}
Without the HashSet, you’ll traverse k times for each element, in order to compare to the previous k, meaning O(k*n).
With the HashSet, it’s O(n).
Hi ,
We can do this without the set , right?!
I think if you use two pointers from front and end. then you can do this in O(n).
You are right. My code for this solution:
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashSet set = new HashSet();
for (int i = 0; i = k)
set.remove(nums[i - k]);
}
return false;
}
We can maintain a queue and hashset which only maintain current k elements. But this takes O(k) space.
Is there a way to do this O(n) time and O(1) space though? I’m just thinking how would we go about proving that there isn’t?