数组中未出现的最小正整数
题目描述
给定一个无序数组arr,找到数组中未出现的最小正整数
例如arr = [-1, 2, 3, 4]。返回1
arr = [1, 2, 3, 4]。返回5
[要求]
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)
输入描述:
第一行为一个整数N。表示数组长度。
接下来一行N个整数表示数组内的数
输出描述:
输出一个整数表示答案
示例1
输入
4
-1 2 3 4
输出
1
示例2
输入
4
1 2 3 4
输出
5
备注:
1
⩽
N
⩽
1
0
6
1 \leqslant N \leqslant 10^6
1⩽N⩽106
−
1
0
9
⩽
a
r
r
i
⩽
1
0
9
-10^9 \leqslant arr_i \leqslant 10^9
−109⩽arri⩽109
法一:
- 使用两个指针 l、r,l 表示遍历到目前为止,数组已经包含的正整数范围是 [1, l] ,所以开始 l = 0 ;r 表示遍历到目前为止,在后续出现最优状况的情况下,arr 可能包含的正整数范围是 [1, r] ,所以开始时 r = n;
- 从左到右遍历 arr ,遍历到位置 l ,位置 l 的数为 arr[l];
- 若 arr[l] == l + 1,在没有遍历到 arr[l] 之前,arr 已经包含的正整数范围是 [1, l] ,此时出现 arr[l] == l + 1,所以 arr 包含的正整数范围可以扩展到 [1, l+1] ,即 l++;
- 若 arr[l] <= l,因为没有遍历到 arr[l] 之前,arr 在后续最优的情况下可能包含的正整数范围是 [1, l],需要的是 [l+1, r] 范围上的数,此时出现了 arr[l] <= l,说明 [l+1, r] 范围上的数字少了一个,所以 arr 在后续最优的情况下,可能包含的正整数范围缩小了,变为 [1, r-1] ,此时把 arr 最后位置的数(arr[r-1]) 放在位置 l 上,下一步继续检查这个数字,然后 --r ;
- 若 arr[l] > r,同上;
- 若 arr[ arr[l]-1 ] == arr[l],此时说明 arr[l] 在 [l+1, r] 范围内,而 arr[l] 应该在 arr[l] - 1 位置上,但是 arr[ arr[l]-1 ] == arr[l] ,说明出现了两个 arr[l] ,同样的,[l+1, r] 范围上的数又少了一个,操作同上;
- 此时此刻,说明发现了 [l+1, r] 范围上的数,且未重复,将其放在 arr[l] - 1 位置,继续判断 l 位置上新的元素;
- 最终 l 和 r 位置会碰到一起,此时 arr 已经包含的正整数范围是 [1,l] ,返回 l + 1 即可。
法一代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1000001;
int n;
int a[N];
int main( void ) {
scanf("%d", &n);
for ( int i = 0; i < n; ++i ) {
scanf("%d", a + i);
}
int l = 0, r = n;
while ( l < r ) {
if ( a[l] == l + 1 ) ++l;
else if ( a[l] <= l || a[l] > r || a[a[l] - 1] == a[l] ) {
a[l] = a[--r];
} else swap( a[l], a[a[l]-1] );
}
return 0 * printf("%d\n", l + 1);
}
法二:
建立一个大小为 n 的哈希表,把 1 <= arr[i] <= n 的元素标记,然后从 1~n 遍历,若 hash[i] == 0 ,说明 i 是数组中未出现的最小正整数,直接输出即可。
法二代码:
#include <cstdio>
using namespace std;
const int N = 1000001;
int n;
bool a[N];
int main( void ) {
scanf("%d", &n);
int val;
for ( int i = 0; i < n; ++i ) {
scanf("%d", &val);
if ( val <= 0 || val > n ) continue;
a[val] = true;
}
for ( int i = 1; i <= n; ++i ) {
if ( !a[i] ) return 0 * printf("%d\n", i);
}
return 0 * printf("%d\n", n + 1);
}