博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
First Missing Positive
阅读量:6181 次
发布时间:2019-06-21

本文共 3417 字,大约阅读时间需要 11 分钟。

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.

思路:

要求用O(n)的时间想到用hash,又要求用constant space就考虑使用原数组的空间来实现hash。

其中一种思路是把A[i]映射到A[A[i]-1]上,把A[A[i]-1]赋值为负表示A[i]已被映射。最后从前至后扫描一遍A,找到第一个大于零的A[i],结果就是i+1。

需要注意的是A[i]小于等于零,以及A[i]大于数组大小的情况。

以下是参考博客():

O(n^2)的算法是最直观的思路,枚举1~n,然后检查是否存在。

 

O(nlogn)的算法也不难想到,对数组排序,然后遍历数组。

 

如果允许O(n)的空间,利用一个hash数组,也能够实现O(n)的算法。

 

现在题目给予的是常量空间,要求实现O(n)的算法。

网上很多同学的blog都给出了基于hash的思想的一个O(n)的算法。

大致思路:

        既然不允许使用额外的数组作为hash数组,那么就考虑让原数组多带点信息。

        第一步,假设原数组都是正数,那么我们可以考虑将相应位置的正数变成负数来表示该位置已经出现过。听上去有些抽象,举个例子:

                         0  1  2  3  4  5  6  7  8  9

                A =   9  7  6  5  3  1  4  5  8  4

                由于数组下标都是从0到n-1,而我们要考虑的是1到n,所以要从[0, n-1]映射到[1, n]。

                |A[0]| (绝对值符号) = 9,所以我们将A[9 - 1([1,n]映射到[0, n-1])]  即A[8]置为-A[8]。

 

                         0  1  2  3  4  5  6  7  8  9

                A =   9  7  6  5  3  1  4  5 -8  4

                |A[1]| = 7,A[7-1]即A[6]=-A[6]。

                        0  1  2  3  4  5  6  7  8  9

                A =   9  7  6  5  3  1  -4  5 -8  4

                |A[2]|=6,A[5]=-A[5]。

 

                        0  1  2  3  4  5  6  7  8  9

                A =   9  7  6  5  3  -1  -4  5 -8  4

 

               最终:

 

                         0  1   2   3   4   5   6   7  8  9

                A =   -9  7  -6  -5  -3  -1  -4  -5 -8  4

 

        第二步,很简单了,遍历数组A,看哪一位不是负数,则该位下标+1则是所求。

        对上例,A[1]=7,所以First Missing Positive是2。

 

        

        假设存在负数和0,则可以将这些全部置为一个无穷大(或者N+1)的正数即可。在置反时,如果A[i]超出了范围,则不理会。

        例如:

 

                         0  1  2  3  4  5  6  7  8  9

                A =   9  7  6  5  3  1  4  -5  8  4

                预处理后变为:

 

                        0  1  2  3  4  5  6  7   8  9

                A =   9  7  6  5  3  1  4  11(N+1)  8  4

                最终:

 

                          0  1   2   3   4   5   6   7   8   9

                A =   -9  7  -6  -5  -3  -1  -4  -11 -8  4

我采用了另外一种方法。

        大致思路:

                第一步,遍历数组,如果A[i]不等于i+1,也就是相应数字没有出现在该出现的位置上,则交换A[i]和A[A[i] - 1],直到A[i]<=0或者A[i]>N或者A[i]==i+1为止。

                第二步,遍历数组,第一个满足A[i] != i+1的i,First missing positive为i+1。

 

        

        举例说明:

                      0 1 2

                A = 0 1 3

                A[0] = 0,满足A[i]<=0的条件,不作变动。

                A[1] = 1,交换A[1]和A[A[1] - 1]即A[0],得到:

 

                     0 1 2

               A = 1 0 3

               A[2] = 3,满足A[i] == i + 1的条件,不作变动。

               

               遍历数组,发现A[1] != 2,因此First Missing Positive为2.

        P.S.

             0 1

       A = 1 1

       会陷入不断的交换之中,因此需要再加一个终止条件:上次交换的数和这次的相同,则没必要交换。

代码:

1     int firstMissingPositive(int A[], int n) { 2         // IMPORTANT: Please reset any member data you declared, as 3         // the same Solution instance will be reused for each test case. 4         int i, j; 5         int max = 0; 6         if(n == 0) 7             return 1;    8         for(i = 0; i < n; i++){ 9             if(A[i] > max && A[i] <= n){10                 max = A[i];11             }12         }13         for(i = 0; i < n; i++){14             if(A[i] <= 0)15                 A[i] = max+1;16         }17         for(i = 0; i < n; i++){18             if(abs(A[i]) <= max && abs(A[i]) <= n){19                 if(A[abs(A[i])-1] > 0)20                     A[abs(A[i])-1] = -A[abs(A[i])-1];             21            }22         }23         for(i = 0; i < n; i++){24             if(A[i] > 0){25                 return i+1;26             }27         }28         return max+1;29     }

 第二次代码写得比参考文献里的要清楚些,其实只要把小于等于0的数处理为大于n的数即可。

1     int firstMissingPositive(int A[], int n) { 2         // IMPORTANT: Please reset any member data you declared, as 3         // the same Solution instance will be reused for each test case. 4         if(n == 0) 5             return 1; 6         int i; 7         for(i = 0; i < n; i++){ 8             if(A[i] <= 0) 9                 A[i] = n+1;10         }11         for(i = 0; i < n; i++){12             if(abs(A[i]) <= n && A[abs(A[i])-1] > 0)13                 A[abs(A[i])-1] = -A[abs(A[i])-1];14         }15         for(i = 1; i <= n; i++){16             if(A[i-1] > 0)17                 return i;18         }19         return i;20     }

 

转载于:https://www.cnblogs.com/waruzhi/p/3421418.html

你可能感兴趣的文章
Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示
查看>>
第三天
查看>>
connector for python
查看>>
等价类划分的应用
查看>>
Web Service(下)
查看>>
trigger()
查看>>
nvm 怎么安装 ?
查看>>
Java VM里的magic
查看>>
[Node.js]Domain模块
查看>>
Linux操作系统文档
查看>>
利用Tensorflow训练自定义数据
查看>>
c++官方文档-枚举-联合体-结构体-typedef-using
查看>>
[题解]UVA11029 Leading and Trailing
查看>>
利用vue-gird-layout 制作可定制桌面 (一)
查看>>
校园社交网站app
查看>>
如何指定某些文件关闭ARC
查看>>
4、跃进表
查看>>
JAVA面向对象的总结(静态函数与static关键字)
查看>>
课堂作业第四周课上作业一
查看>>
使用Java语言开发微信公众平台(七)——音乐消息的回复
查看>>