Hello, reader ๐๐ฝ ! Welcome to day 21 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.
Today, I will be picking up LeetCode's daily challenge problem: 1219. Contains Duplicate II.
๐ค Problem Statement
- Given an array of integers and a number k, find if there exists two indices, i and j such that,
nums[i] == nums[j]
andabs(i - j) <= k
. Return true if such indices exists or false. - E.g.:
nums = [1,2,3,1], k = 3
=>true
nums = [1,2,3,1,2,3], k = 2
=>false
๐ฌ Thought Process - Brute Force
- The simplest and least efficient way to handle would be to use two loops and check for every possible pair.
- If a pair is found that satisfies:
nums[i] == nums[j]
andabs(i - j) <= k
, we return true. - Else, we keep doing this until all the pairs have been checked.
๐ฉ๐ฝโ๐ป Solution - Brute Force
Below is the code for the above discussed brute force approach.
class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { if(nums == null || nums.length == 0) { return false; } int n = nums.length; for(int i = 0; i < n-1; i++) { int n1 = nums[i]; for(int j = i+1; j < n; j++) { int n2 = nums[j]; if(n1 != n2) { continue; } int diff = Math.abs(i-j); if(diff <= k) { return true; } } } return false; } }
Time Complexity: O(n^2) - n = number of integers in the array Space Complexity: O(1)
๐ฌ Thought Process - Hash Table
- We can bring down the time complexity to
O(n)
by mapping every value to it's index. - While processing each number in the array, if it's already in the map, we check the value of the current index with the mapped index of the number in the map.
- If the two indices satisfy the condition, we return true. Else, we replace the previous index in the map with the current index.
๐ฉ๐ฝโ๐ป Solution - Hash Table
Below is the code for the above discussed hash table approach.
class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { if(nums == null || nums.length == 0) { return false; } int n = nums.length; Map<Integer, Integer> map = new HashMap(); for(int i = 0; i<n; i++) { int num = nums[i]; if(map.containsKey(num)) { int j = map.get(num); int diff = Math.abs(i-j); if(diff <= k) { return true; } } // Update the index because any future occurrences // of the number could be within index [i, i+k] map.put(num, i); } return false; } }
Time Complexity: O(n) - n = number of integers in the array - We are traversing through all n elements. Space Complexity: O(n) - n = number of integers - We are using a map to hold pairs of n numbers and their indices
๐ฌ Thought Process - Sliding Window
- We can bring down the time complexity to
O(n)
by mapping every value to it's index. - While processing each number in the array, if it's already in the map, we check the value of the current index with the mapped index of the number in the map.
- If the two indices satisfy the condition, we return true. Else, we replace the previous index in the map with the current index.
๐ฉ๐ฝโ๐ป Solution - Sliding Window
Below is the code for the above discussed brute force approach.
class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { if(nums == null || nums.length == 0) { return false; } int n = nums.length; Set<Integer> set = new HashSet(); int left = 0, right = 0; while(right < n) { int num = nums[right]; if(right - left > k) { set.remove(nums[left]); left++; } if(set.contains(num)) { return true; } set.add(num); right++; } return false; } }
Time Complexity: O(n) - n = number of integers in the array - We are traversing through all n elements. Space Complexity: O(n) - n = number of integers - We are using a map to hold pairs of n numbers and their indices Space Complexity: O(n)
We can also avoid keeping track of pointers and maintain a set with only k elements.
- Every time the we come across
(k+1)st
element, we remove the left most element. - While adding the next element if it is already present in the set, then we know that the condition is satisfied, and return true.
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null || nums.length == 0) {
return false;
}
int n = nums.length;
Set<Integer> set = new HashSet();
for(int i = 0; i<n; i++) {
int num = nums[i];
// If the window of [i, i+k] is done
// remove the left most number
if(i > k) {
int leftMostNum = i-k-1;
set.remove(nums[leftMostNum]);
}
if(!set.add(num)) {
return true;
}
}
return false;
}
}
Conclusion
That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!
Thank you for reading!