Find the smallest positive number missing from an unsorted array

本文介绍了一种O(n)时间复杂度且使用常数额外空间的算法,用于查找未排序数组中最小的正整数缺失值。通过分步操作:首先分离出所有非正数,然后利用数组元素作为索引来标记正数的存在,最后再次遍历以找到第一个未被标记的正数位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



You are given an unsorted array with both positive and negative elements. You have to find the smallest positive number missing from the array in O(n) time using constant extra space. You can modify the original array. 

Examples

 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 

Source: To find the smallest positive no missing from an unsorted array

naive method to solve this problem is to search all positive integers, starting from 1 in the given array. We may have to search at most n+1 numbers in the given array. So this solution takes O(n^2) in worst case.

We can use sorting to solve it in lesser time complexity. We can sort the array in O(nLogn) time. Once the array is sorted, then all we need to do is a linear scan of the array. So this approach takes O(nLogn + n) time which is O(nLogn).

We can also use hashing. We can build a hash table of all positive elements in the given array. Once the hash table is built. We can look in the hash table for all positive integers, starting from 1. As soon as we find a number which is not there in hash table, we return it. This approach may take O(n) time on average, but it requires O(n) extra space.

A O(n) time and O(1) extra space solution:
The idea is similar to this post. We use array elements as index. To mark presence of an element x, we change the value at the index x to negative. But this approach doesn’t work if there are non-positive (-ve and 0) numbers. So we segregate positive from negative numbers as first step and then apply the approach.

Following is the two step algorithm.
1) Segregate positive numbers from others i.e., move all non-positive numbers to left side. In the following code, segregate() function does this part.
2) Now we can ignore non-positive elements and consider only the part of array which contains all positive elements. We traverse the array containing all positive numbers and to mark presence of an element x, we change the sign of value at index x to negative. We traverse the array again and print the first index which has positive value. In the following code, findMissingPositive() function does this part. Note that in findMissingPositive, we have subtracted 1 from the values as indexes start from 0 in C.

/* Program to find the smallest positive missing number */
#include <stdio.h>
#include <stdlib.h>
 
/* Utility to swap to integers */
void swap( int *a, int *b)
{
     int temp;
     temp = *a;
     *a   = *b;
     *b   = temp;
}
 
/* Utility function that puts all non-positive (0 and negative) numbers on left
   side of arr[] and return count of such numbers */
int segregate ( int arr[], int size)
{
     int j = 0, i;
     for (i = 0; i < size; i++)
     {
        if (arr[i] <= 0) 
        {
            swap(&arr[i], &arr[j]);
            j++;  // increment count of non-positive integers
        }
     }
 
     return j;
}
 
/* Find the smallest positive missing number in an array that contains
   all positive integers */
int findMissingPositive( int arr[], int size)
{
   int i;
 
   // Mark arr[i] as visited by making arr[arr[i] - 1] negative. Note that
   // 1 is subtracted because index start from 0 and positive numbers start from 1
   for (i = 0; i < size; i++)
   {
     if ( abs (arr[i]) - 1 < size && arr[ abs (arr[i]) - 1] > 0)
       arr[ abs (arr[i]) - 1] = -arr[ abs (arr[i]) - 1];
   }
 
   // Return the first index value at which is positive
   for (i = 0; i < size; i++)
     if (arr[i] > 0)
       return i+1;  // 1 is added becuase indexes start from 0
 
   return size+1;
}
 
/* Find the smallest positive missing number in an array that contains
   both positive and negative integers */
int findMissing( int arr[], int size)
{
    // First separate positive and negative numbers
    int shift = segregate (arr, size);
 
    // Shift the array and call findMissingPositive for
    // positive part
    return findMissingPositive(arr+shift, size-shift);
}
 
int main()
{
   int arr[] = {0, 10, 2, -10, -20};
   int arr_size = sizeof (arr)/ sizeof (arr[0]);
   int missing = findMissing(arr, arr_size);
   printf ( "The smallest positive missing number is %d " , missing);
   getchar ();
   return 0;
}

Output:

The smallest positive missing number is 1 

Note that this method modifies the original array. We can change the sign of elements in the segregated array to get the same set of elements back. But we still loose the order of elements. If we want to keep the original array as it was, then we can create a copy of the array and run this approach on the temp array.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above


You are given an unsorted array with both positive and negative elements. You have to find the smallest positive number missing from the array in O(n) time using constant extra space. You can modify the original array. 

Examples

 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 

Source: To find the smallest positive no missing from an unsorted array

naive method to solve this problem is to search all positive integers, starting from 1 in the given array. We may have to search at most n+1 numbers in the given array. So this solution takes O(n^2) in worst case.

We can use sorting to solve it in lesser time complexity. We can sort the array in O(nLogn) time. Once the array is sorted, then all we need to do is a linear scan of the array. So this approach takes O(nLogn + n) time which is O(nLogn).

We can also use hashing. We can build a hash table of all positive elements in the given array. Once the hash table is built. We can look in the hash table for all positive integers, starting from 1. As soon as we find a number which is not there in hash table, we return it. This approach may take O(n) time on average, but it requires O(n) extra space.

A O(n) time and O(1) extra space solution:
The idea is similar to this post. We use array elements as index. To mark presence of an element x, we change the value at the index x to negative. But this approach doesn’t work if there are non-positive (-ve and 0) numbers. So we segregate positive from negative numbers as first step and then apply the approach.

Following is the two step algorithm.
1) Segregate positive numbers from others i.e., move all non-positive numbers to left side. In the following code, segregate() function does this part.
2) Now we can ignore non-positive elements and consider only the part of array which contains all positive elements. We traverse the array containing all positive numbers and to mark presence of an element x, we change the sign of value at index x to negative. We traverse the array again and print the first index which has positive value. In the following code, findMissingPositive() function does this part. Note that in findMissingPositive, we have subtracted 1 from the values as indexes start from 0 in C.

/* Program to find the smallest positive missing number */
#include <stdio.h>
#include <stdlib.h>
 
/* Utility to swap to integers */
void swap( int *a, int *b)
{
     int temp;
     temp = *a;
     *a   = *b;
     *b   = temp;
}
 
/* Utility function that puts all non-positive (0 and negative) numbers on left
   side of arr[] and return count of such numbers */
int segregate ( int arr[], int size)
{
     int j = 0, i;
     for (i = 0; i < size; i++)
     {
        if (arr[i] <= 0) 
        {
            swap(&arr[i], &arr[j]);
            j++;  // increment count of non-positive integers
        }
     }
 
     return j;
}
 
/* Find the smallest positive missing number in an array that contains
   all positive integers */
int findMissingPositive( int arr[], int size)
{
   int i;
 
   // Mark arr[i] as visited by making arr[arr[i] - 1] negative. Note that
   // 1 is subtracted because index start from 0 and positive numbers start from 1
   for (i = 0; i < size; i++)
   {
     if ( abs (arr[i]) - 1 < size && arr[ abs (arr[i]) - 1] > 0)
       arr[ abs (arr[i]) - 1] = -arr[ abs (arr[i]) - 1];
   }
 
   // Return the first index value at which is positive
   for (i = 0; i < size; i++)
     if (arr[i] > 0)
       return i+1;  // 1 is added becuase indexes start from 0
 
   return size+1;
}
 
/* Find the smallest positive missing number in an array that contains
   both positive and negative integers */
int findMissing( int arr[], int size)
{
    // First separate positive and negative numbers
    int shift = segregate (arr, size);
 
    // Shift the array and call findMissingPositive for
    // positive part
    return findMissingPositive(arr+shift, size-shift);
}
 
int main()
{
   int arr[] = {0, 10, 2, -10, -20};
   int arr_size = sizeof (arr)/ sizeof (arr[0]);
   int missing = findMissing(arr, arr_size);
   printf ( "The smallest positive missing number is %d " , missing);
   getchar ();
   return 0;
}

Output:

The smallest positive missing number is 1 

Note that this method modifies the original array. We can change the sign of elements in the segregated array to get the same set of elements back. But we still loose the order of elements. If we want to keep the original array as it was, then we can create a copy of the array and run this approach on the temp array.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值