给定一个未排序的数组,其中同时包含正和负元素。使用恒定的额外空间在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)