Written interview questions: find the smallest positive integer missing

     Originally published in:

 

     The National Day holiday has passed halfway. Today, let's look at a leetcode question, which was also an interview question for company B that year, which was difficult. Questions are as follows:

 

     Given an integer array, find the smallest positive integer missing in it. The time complexity is O(n) and the space complexity is O(1). Examples of input and output are as follows:

Input array a Output
[1, 2, 0] 3
[3, 4, 1, -1] 2
[6, 7, 8, 12] 1

 

      Let's analyze it first:

      A. Assuming that the n elements in a occupy 1~n, then the smallest positive integer missing is n+1.

      B. Assuming that the n elements in a do not completely occupy 1~n, then the smallest positive integer missing must be a number between 1~n.

      Combining A and B, we can see that the missing smallest positive integer must be in the interval [1, n+1]. This is a very important conclusion.

 

Algorithm 1: Brute force algorithm

      The brute force algorithm is very simple. It traverses the interval [1, n+1] directly, and then determines whether the element is in a. At this time, the time complexity is O(n*n), and the space complexity is O(1).  

       Obviously, the interview cannot be passed.        

 

Algorithm 2: Hash Algorithm

      From the brute force algorithm, this is nothing more than a search problem, so you can consider using a hash table. That is, use the hash table to record the a array, and then directly traverse the interval [1, n+1] to determine whether the element is in the hash table. At this time, the time complexity and space complexity are both O(n).

       Obviously, the interview cannot be passed.

 

Algorithm 3: Clever Notation

      We refer to Algorithm 2 and make smart optimizations when marking the presence of elements.

      Taking a = [3, 4, 1, -1] as an example, n = 4, the process is as follows:

Original array [3, 4, 1, -1]
Non-positive number changed to n+1 [3, 4, 1, 5]
3 exists, identified by the minus sign of a[3-1] [3, 4, -1, 5]
4 exists, identified by the minus sign of a[4-1] [3, 4, -1, -5]
1 exists, identified by the minus sign of a[1-1] [-3, 4, -1, -5]
a[x-1]=4, is a positive number, so x must not exist x=2 is the smallest positive integer missing


      It can be seen that when recording whether the element x exists, the symbol of a[x-1] is used, where the interval of x is [1, n]. The time complexity of this algorithm is O(n), and the space is complicated The degree is O(1), which fully meets the requirements of the question. This marking method is very clever, and it is really not easy to think of.

      Now that the steps of the algorithm are determined, the corresponding program is relatively simple, let's take a look:


package main
import "fmt"

func abs(x int) int {
    if x < 0 {
        return -x
    }
  
    return x
}

func solution(a []int) int {
    n := len(a)
    for i := 0; i < n; i++ {
        if a[i] <= 0 {
            a[i] = n + 1
        }
    }
  
    for i := 0; i < n; i++ {
        num := abs(a[i])
        if num <= n {
            a[num - 1] = -abs(a[num - 1])
        }
    }
  
    for i := 0; i < n; i++ {
        if a[i] > 0 {
            return i + 1
        }
    }
  
    return n + 1
}

func main() {
  a := []int{3, 4, 1, -1}
  fmt.Println(solution(a))
}

      Result: 2

 

Algorithm 4: Replacement homing method

      Algorithm 3 is more difficult to think of, so let's look at a more intuitive idea. For the element i of the array a, if i is in the interval [1, n], it can be returned to the position by permutation and put i at a[i-1], as follows:

 

Input array a Replacement target
[1, 2, 0] [1, 2, 0]
[3, 4, 1, -1] [1, -1, 3, 4]
[6, 7, 8, 12] [6, 7, 8, 12]

 

     After replacement, traverse a again. If a[x-1] and x are not equal, then x must be the smallest positive integer missing, as follows:

Replacement target x (the smallest positive integer missing)
[1, 2, 0] 3
[1, -1, 3, 4] 2
[6, 7, 8, 12] 1

 

     The time complexity of the algorithm is O(n), and the space complexity is O(1), which fully meets the requirements of the problem. Now that the algorithm is determined, the corresponding program is relatively simple, as follows:

package main
import "fmt"

func solution(a []int) int {
    n := len(a)
    for i := 0; i < n; i++ {
        // 注意:下面这里要用for, 而不是if.
        for a[i] > 0 && a[i] <= n && a[a[i]-1] != a[i] {
            a[a[i]-1], a[i] = a[i], a[a[i]-1]
        }
    }
  
    for i := 0; i < n; i++ {
        if a[i] != i + 1 {
            return i + 1
        }
    }
  
    return n + 1
}

func main() {
  a := []int{3, 4, 1, -1}
  fmt.Println(solution(a))
}

      Result: 2

 

 

      To sum up: Algorithm 1 and Algorithm 2 cannot pass the interview, Algorithm 3 and Algorithm 4 can pass the interview. Among them, Algorithm 3 is more circumstantial, and it is not easy to think of at the interview site. In comparison, Algorithm 4 is intuitive and easy to understand. When the program is implemented, it should be noted that the inner layer should use for instead of if.

 

      Overall, the interview requirements of B company are still very high, I wish you all the offers you like.

Guess you like

Origin blog.csdn.net/stpeace/article/details/109544261