First Missing Positive
题目:
Given an unsorted integer array, find the first missing positive integer.
For example,
Given[1,2,0]
return3
,
and[3,4,-1,1]
return2
.Your algorithm should run in O(n) time and uses constant space.
开始理解题目的点问题,以为是漏掉的一个数,其实应该是第一个漏掉的自然数,这里自然数当然不包括0。所以只要从1开始每次加一看哪一个数没有出现在列表中就得到结果了,关键是怎么依次查呢?当时没想到办法,后来有人说是hash。这貌似可以,但空间不是常数空间,需要一个空间把数都映射进去,接着突然想到把当前元素的位置与它的值对应的位置作交换,比如[3,4,-1,1]中,元素3放到第三个位置上去得到[-1,4,3,1],接着再往下交换,如果当前位置的值小于1或者大于长度n都抛弃,直接扫描下一个元素。最后再从列表头开始扫描,直到漏网之鱼的出现。比如上面的例子最后得到[1,-1,3,4]这样扫描发现1后面不是2所以结果就是2。代码如下:
1 int firstMissingPositive(int A[], int n) { 2 for(int i=0;i<n;i++){ 3 while(A[i]>0&&A[i]<=n&&A[i]!=i+1&&A[A[i]-1]!=A[i]){ 4 swap_v(&A[A[i]-1],&A[i]); 5 } 6 } 7 int j; 8 for(j=0;j<n&&A[j]==j+1;j++){} 9 return j+1; 10 } 11 void swap_v(int *a,int* b){ 12 int t = *a; 13 *a = *b; 14 *b = t; 15 }
其中要注意一下当前的元素是否和要交换位置的元素是相同的值,或者本身就是已经在自己的位置上。写完代码后看一下时间复杂度是多大?看到两个嵌套循环时误以为是O(n2)可能要过不了大集合了,结果12ms全pass了,其实仔细一想,第一个元素经过一次交换都能到达自己最终的位置上,对于长度为n的列表,至多n次交换就可以得到元素的最终位置结果,时间复杂度是O(n)啦。