219. Contains Duplicate II

219. Contains Duplicate II

Problem Solving - Day 21

ยท

5 min read

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] and abs(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] and abs(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!