645. Set Mismatch

645. Set Mismatch

Problem Solving - Day 23

ยท

5 min read

Hello, reader ๐Ÿ‘‹๐Ÿฝ ! Welcome to day 23 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: 645. Set Mismatch.


๐Ÿค” Problem Statement

  • Given an array of integers 1 to n, one of the numbers is missing and another appears twice.
  • Find the number that occurs twice and the number that is missing and return them in the form of an array.
  • E.g.:
    • nums = [1,2,2,4] => [2,3]
    • nums = [2,3,2] => [2,1]

๐Ÿ’ฌ Thought Process - Brute Force

  • The straightforward and brute force approach would be to check for every occurrence of all the numbers from 1 to n in the array.
  • We maintain a count for every number. If the count for a number is 2 that means it occurs twice.
  • If the count for a number after the inner loop executes is 0, that means it's missing in the array.

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Brute Force

  • Below is the code for the brute force approach.

    class Solution {
      public int[] findErrorNums(int[] nums) {
          if(nums == null || nums.length < 2) {
              return new int[0];
          }
    
          int n = nums.length;
          int[] missing = new int[2];
    
          for(int i = 1; i <= n; i++) {
              int count = 0;
              for(int j = 0; j < n; j++) {
                  if(nums[j] == i) {
                      count++;
                  }
                  if(count == 2) {
                      missing[0] = i;
                      if(missing[1] != 0) {
                          return missing;
                      }
                  }
              }
              if(count == 0) {
                  missing[1] = i;
                  if(missing[0] != 0) {
                      return missing;
                  }
              }
          }
    
          return missing;
      }
    }
    
    Time Complexity: O(n^2)
      - n = number of elements
      - We check the entire array for all numbers 1 to n
    Space Complexity: O(1)
    

๐Ÿ’ฌ Thought Process - Sorting

  • We can sort the array so that the numbers that appears twice occur together. This way it's easy to find out the number appearing twice.
  • And to find which number is missing we can figure out which number in the array satisfies num[i] - num[i-1] > 1, where 0 <= i < n.
  • For e.g.: if the numbers after sorting are: [1,2,2,4] then we can clearly see for i=3, num[3] - num[2] > 1. Hence the missing number is 3.
  • One edge case is when n is the missing number in the array. For e.g.: if nums = [1,2,2], then 3 is missing in the array.
  • In such a case, we will fail to find an element where nums[i] - nums[i-1] > 2. In this case, once the loop terminates we will have to check if the last element in the array is not equal to n. If this is true, then update the missing number as n.
  • Let's look at the code now.

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Sorting

  • The code for the sorted approach is below.

    class Solution {
      public int[] findErrorNums(int[] nums) {
          if(nums == null || nums.length < 2) {
              return new int[0];
          }
    
          int n = nums.length;
          int[] missing = new int[2];
    
          Arrays.sort(nums);
    
          for(int i = 0; i<n; i++) {
              int num = nums[i];
              int prev = i > 0 ? nums[i-1] : 0;
              if(i > 0 && prev == num) {
                  missing[0] = num;
              }
              else if(num > prev+1) {
                  missing[1] = num-1;
              }
          }
    
          if(nums[n-1] != n) {
              missing[1] = n;
          }
          return missing;
      }
    }
    
    Time Complexity: O(n logn)
      - n = number of elements
      - since we are sorting the array
    Space Complexity: O(1)
    

๐Ÿ’ฌ Thought Process - Hash Table

  • To bring down the solution to O(n), we can use a hash map that stores the number in the array and their frequency in key, value pairs.
  • Then we can iterate over all the numbers from 1 to n to find both the missing number whose frequency is not in the map and the number that appears twice.

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Hash Table

  • Below is the code for the approach using hash map.

    class Solution {
      public int[] findErrorNums(int[] nums) {
          if(nums == null || nums.length < 2) {
              return new int[0];
          }
    
          int n = nums.length;
          int[] missing = new int[2];
    
          Map<Integer, Integer> frequency = new HashMap();
    
          for(int i = 0; i<n; i++) {
              int num = nums[i];
              frequency.put(num, frequency.getOrDefault(num, 0) + 1);
          }
    
          for(int i = 1; i <= n; i++) {
              if(!frequency.containsKey(i)) {
                  missing[1] = i;
              }
              else if(frequency.get(i) == 2) {
                  missing[0] = i;
              }
          }
    
          return missing;
      }
    }
    
    Time Complexity: O(n)
      - n = number of elements
    Space Complexity: O(n)
      - n = number of elements
      - we store the num and it's frequency in a map
    

๐Ÿ’ฌ Thought Process - Count Sort

  • We can using counting sort to sort all the n numbers such that every number i appears at index i-1.
  • This way we will know which number is missing and that appears twice when the index and number doesn't match.
  • The speciality is that this takes only O(n) and no extra space.
  • To visualise, let's take the following example: nums = [8,7,3,5,3,6,1,4]. image.png

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Count Sort

  • Below is the code for the count sort approach.

    class Solution {
      public int[] findErrorNums(int[] nums) {
          if(nums == null || nums.length < 2) {
              return new int[0];
          }
    
          int n = nums.length;
          int[] missing = new int[2];
    
          int i = 0;
          while(i < n) {
              int num = nums[i];
              int index = num-1;
              if(nums[index] != num) {
                  // update the index
                  int temp = nums[index];
                  nums[i] = temp;
                  nums[index] = num;
              }
              else {
                  i++;
              }
          }
    
          i = 0;
          while(i < n) {
              int num = nums[i];
              int index = num-1;
    
              if(num != i+1) {
                  missing[0] = num;
                  missing[1] = i+1;
                  break;
              }
              i++;
          }
    
          return missing;
      }
    }
    
    Time Complexity: O(n)
      - n = number of elements
    Space Complexity: O(1)
    

  • There's another solution that uses bitwise XOR as well. You can find it on LeetCode solution section.

  • You can find the code for this question in the GitHub repo here: 645. Set Mismatch.

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!