题目
Given an unsorted integer array, find the first missing positive integer.
For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.Your algorithm should run in O(n) time and uses constant space.
解题思路
大概意思就是找到给出的未排序的数组中未出现的最小正整数。
1. Brute - Force
最简单的方法当然是蛮力,不停循环测试从1开始到n(n为数组大小)是否在数组中,这样的时间复杂度为O( n2 ),不使用额外空间。
2. 排序(快排、归并、堆、谢尔)
更进一步的,可以使用排序的方法,把时间复杂度降到O(nlogn),不适用额外空间。
3. hash表
还可以使用hash表,因为题目中要求的是正整数,所以映射起来相当方便,申请一个和数据数组一样大的数组,把从1到n之间的数映射到hash表中,之后检查一次hash表即可。
时间复杂度O(n),空间复杂度O(n)。
4.桶排序
上面提到的3种方法性能逐渐在好转,但是还打不到这道题要求的时间复杂度O(n),常数空间的要求。应该是要使用桶排序。
而且这道题里面需要处理的是有很明确的上下界(0,n)的正整数,恰好可以使用桶排序。
代码如下:
/**
* Definition for an integer array.
* struct IntArray {
* int* elements;
* int size;
* };
*/
int firstMissingPositive(struct IntArray* nums) {
int *n=nums->elements,r;
for (int i=0;i<nums->size;i++)
{
if (n[i]<1||n[i]>nums->size)
continue;
else if (n[i]!=n[n[i]-1])
{
r=n[n[i]-1];
n[n[i]-1]=n[i];
n[i]=r;
i--;
}
}
for (int i=0;i<nums->size;i++)
if (n[i]!=i+1)
return i+1;
return nums->size+1;
}
在使用桶排序的过程中,代码里出现了2个小问题:
忘记对交换后的数排序。如3、4、-1、1排序:
排序到这一步就算结束了,没有去跟踪-1、1的排序。上面代码里
i--
就是为了解决这个问题。将一个闭环中的所有数全都排序后,再检验下一个。
最后,对数组循环,找到第一个值与索引下标不一致的数返回索引即可。