📌  相关文章
📜  查找未排序数组中缺少的最小正数|套装2

📅  最后修改于: 2021-04-29 17:18:32             🧑  作者: Mango

给定一个未排序的数组,其中同时包含正和负元素。使用恒定的额外空间在O(n)时间内找到数组中丢失的最小正数。允许修改原始数组。
例子:

Input:  {2, 3, 7, 6, 8, -1, -10, 15}
Output: 1

Input:  { 2, 3, -7, 6, 8, 1, -10, 15 }
Output: 4

Input: {1, 1, 0, -1, -2}
Output: 2 
推荐:在继续解决方案之前,请先在“实践”上解决它。

在上一篇文章中,我们讨论了O(n)时间和O(1)额外空间解决方案。在这篇文章中,讨论了另一种替代解决方案。
我们使与给定数组元素对应的索引处的值等于数组元素。例如:考虑数组= {2,3,7,6,6,8,-1,-10,15}。为了标记此数组中元素2的存在,我们使arr [2-1] =2。在数组下标[2-1]中,2是要标记的元素,而1减去了1,因为我们正在映射元素值范围索引值范围为[0,N-1]的[1,N]。但是,如果我们使arr [1] = 2,我们将丢失存储在arr [1]中的数据。为避免这种情况,我们首先存储存在于arr [1]的值,然后对其进行更新。接下来,我们将标记先前在arr [1](即3)处存在的元素的存在。显然,这会导致在数组上进行某种类型的随机遍历。现在我们必须指定一个条件来标记此遍历的结束。有三个条件标记此遍历的结束:
1.如果要标记的元素为负:无需标记此元素的存在,因为我们有兴趣查找第一个缺失的正整数。因此,如果找到了否定元素,则只需结束遍历即可,因为不再做任何标记元素存在的标记。
2.如果要标记的元素大于N:无需标记此元素的存在,因为如果存在此元素,则可以肯定地它已替换了[1,N]范围内的元素。大小N,因此确保我们的答案在[1,N]范围内。因此,只需结束遍历即可,因为不再需要标记元素的存在。
3.如果已经标记了当前元素的存在:假设要标记为存在的元素为val。如果arr [val-1] = val,那么我们已经标记了此元素的存在。因此,只需结束遍历即可,因为不再需要标记元素的存在。
另请注意,有可能未在当前遍历中标记范围为[1,N]的数组的所有元素。为了确保该范围内的所有元素都标记为存在,我们检查该范围内的数组的每个元素。如果未标记该元素,则从该数组元素开始新的遍历。
标记所有位于[1,N]范围内的数组元素后,我们检查哪个索引值ind不等于ind + 1。如果arr [ind]不等于ind + 1,则ind + 1是最小的正缺失数。回想一下,我们正在将索引值范围[0,N-1]映射到元素值范围[1,N],因此将1添加到ind。如果未找到此类ind,则数组[1,N]中的所有元素都将存在。因此,第一个缺失的正数是N + 1。
此解决方案如何在O(n)时间内发挥作用?
请注意,在最坏的情况下,范围为[1,N]的每个元素最多要遍历两次。在执行遍历时,首先从范围中的其他元素开始。其次,当检查是否需要从该元素发起新的遍历以标记未标记元素的存在时。在最坏的情况下,数组中存在[1,N]范围内的每个元素,因此所有N个元素都要遍历两次。因此,总计算为2 * n,因此时间复杂度为O(n)。
下面是上述方法的实现:

C++
/* CPP program to find the smallest
  positive missing number */
#include 
using namespace std;
 
// Function to find smallest positive
// missing number.
int findMissingNo(int arr[], int n)
{
    // to store current array element
    int val;
 
    // to store next array element in
    // current traversal
    int nextval;
 
    for (int i = 0; i < n; i++) {
 
        // if value is negative or greater
        // than array size, then it cannot
        // be marked in array. So move to
        // next element.
        if (arr[i] <= 0 || arr[i] > n)
            continue;
 
        val = arr[i];
 
        // traverse the array until we
        // reach at an element which
        // is already marked or which
        // could not be marked.
        while (arr[val - 1] != val) {
            nextval = arr[val - 1];
            arr[val - 1] = val;
            val = nextval;
            if (val <= 0 || val > n)
                break;
        }
    }
 
    // find first array index which is
    // not marked which is also the
    // smallest positive missing
    // number.
    for (int i = 0; i < n; i++) {
        if (arr[i] != i + 1) {
            return i + 1;
        }
    }
 
    // if all indices are marked, then
    // smallest missing positive
    // number is array_size + 1.
    return n + 1;
}
 
// Driver code
int main()
{
    int arr[] = { 2, 3, 7, 6, 8, -1, -10, 15 };
    int arr_size = sizeof(arr) / sizeof(arr[0]);
    int missing = findMissingNo(arr, arr_size);
    cout << "The smallest positive missing number is "
         << missing;
    return 0;
}


Java
/* Java program to find the smallest
positive missing number */
import java.io.*;
 
class GFG {
 
    // Function to find smallest positive
    // missing number.
    static int findMissingNo(int []arr, int n)
    {
        // to store current array element
        int val;
     
        // to store next array element in
        // current traversal
        int nextval;
     
        for (int i = 0; i < n; i++) {
     
            // if value is negative or greater
            // than array size, then it cannot
            // be marked in array. So move to
            // next element.
            if (arr[i] <= 0 || arr[i] > n)
                continue;
     
            val = arr[i];
     
            // traverse the array until we
            // reach at an element which
            // is already marked or which
            // could not be marked.
            while (arr[val - 1] != val) {
                nextval = arr[val - 1];
                arr[val - 1] = val;
                val = nextval;
                if (val <= 0 || val > n)
                    break;
            }
        }
     
        // find first array index which is
        // not marked which is also the
        // smallest positive missing
        // number.
        for (int i = 0; i < n; i++) {
            if (arr[i] != i + 1) {
                return i + 1;
            }
        }
     
        // if all indices are marked, then
        // smallest missing positive
        // number is array_size + 1.
        return n + 1;
    }
     
    // Driver code
    public static void main (String[] args)
    {
        int arr[] = { 2, 3, 7, 6, 8, -1, -10, 15 };
        int arr_size = arr.length;
         
        int missing = findMissingNo(arr, arr_size);
         
        System.out.println( "The smallest positive"
                + " missing number is " + missing);
    }
}
 
// This code is contributed by anuj_67.


Python 3
# Python 3 program to find the smallest
# positive missing number
 
# Function to find smallest positive
# missing number.
def findMissingNo(arr, n):
 
    # to store current array element
 
    # to store next array element in
    # current traversal
    for i in range(n) :
 
        # if value is negative or greater
        # than array size, then it cannot
        # be marked in array. So move to
        # next element.
        if (arr[i] <= 0 or arr[i] > n):
            continue
 
        val = arr[i]
 
        # traverse the array until we
        # reach at an element which
        # is already marked or which
        # could not be marked.
        while (arr[val - 1] != val):
            nextval = arr[val - 1]
            arr[val - 1] = val
            val = nextval
            if (val <= 0 or val > n):
                break
 
    # find first array index which is
    # not marked which is also the
    # smallest positive missing
    # number.
    for i in range(n):
        if (arr[i] != i + 1) :
            return i + 1
 
    # if all indices are marked, then
    # smallest missing positive
    # number is array_size + 1.
    return n + 1
 
# Driver code
if __name__ == "__main__":
    arr = [ 2, 3, 7, 6, 8, -1, -10, 15 ]
    arr_size = len(arr)
    missing = findMissingNo(arr, arr_size)
    print( "The smallest positive",
           "missing number is ", missing)
 
# This code is contributed
# by ChitraNayal


C#
/* C# program to find the smallest
positive missing number */
using System;
 
class GFG
{
    // Function to find smallest
    // positive missing number.
    static int findMissingNo(int []arr,
                             int n)
    {
        // to store current
        // array element
        int val;
     
        // to store next array element
        // in current traversal
        int nextval;
     
        for (int i = 0; i < n; i++)
        {
     
            // if value is negative or greater
            // than array size, then it cannot
            // be marked in array. So move to
            // next element.
            if (arr[i] <= 0 || arr[i] > n)
                continue;
     
            val = arr[i];
     
            // traverse the array until we
            // reach at an element which
            // is already marked or which
            // could not be marked.
            while (arr[val - 1] != val)
            {
                nextval = arr[val - 1];
                arr[val - 1] = val;
                val = nextval;
                if (val <= 0 || val > n)
                    break;
            }
        }
     
        // find first array index which
        // is not marked which is also
        // the smallest positive missing
        // number.
        for (int i = 0; i < n; i++)
        {
            if (arr[i] != i + 1)
            {
                return i + 1;
            }
        }
     
        // if all indices are marked,
        // then smallest missing
        // positive number is
        // array_size + 1.
        return n + 1;
    }
     
    // Driver code
    public static void Main (String[] args)
    {
        int []arr = {2, 3, 7, 6,
                     8, -1, -10, 15};
        int arr_size = arr.Length;
         
        int missing = findMissingNo(arr, arr_size);
         
        Console.Write("The smallest positive" +
                        " missing number is " +
                                      missing);
    }
}
 
// This code is contributed
// by shiv_bhakt.


PHP
 $n)
            continue;
 
        $val = $arr[$i];
 
        // traverse the array until
        // we reach at an element
        // which is already marked
        // or which could not be marked.
        while ($arr[$val - 1] != $val)
        {
            $nextval = $arr[$val - 1];
            $arr[$val - 1] = $val;
            $val = $nextval;
            if ($val <= 0 ||
                $val > $n)
                break;
        }
    }
 
    // find first array index
    // which is not marked
    // which is also the smallest
    // positive missing number.
    for ($i = 0; $i < $n; $i++)
    {
        if ($arr[$i] != $i + 1)
        {
            return $i + 1;
        }
    }
 
    // if all indices are marked,
    // then smallest missing
    // positive number is
    // array_size + 1.
    return $n + 1;
}
 
// Driver code
$arr = array(2, 3, 7, 6, 8,
            -1, -10, 15);
$arr_size = sizeof($arr) /
            sizeof($arr[0]);
$missing = findMissingNo($arr,
                         $arr_size);
echo "The smallest positive " .
         "missing number is " ,
                      $missing;
 
// This code is contributed
// by shiv_bhakt.
?>


Javascript


输出:
The smallest positive missing number is 1

时间复杂度: O(n)
辅助空间: O(1)