码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode第一刷_ First Missing Positive

时间:2014-05-15 03:45:41      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:c++   leetcode   算法   

未排序数组,O(N)时间,常数空间,这道题让我非常清晰的感觉到算法的魅力。

先想一下如果允许用额外空间的话,我们会怎么做,对,我们会建立一个hash表,然后从头到尾的扫描数组,等等,怎么映射呢?有n个数,要找第一个消失的正正整数,那么这个消失的正整数的取值范围是什么呢?[1, n+1],之所以包含n+1是因为如果这n数正好是连续的前n个自然数。那我们就知道了,开一个长为n的哈希表,如果当前扫到得数是[1,n]之间的话,就放到数值减1的位置上,如果不是的话就跳过,然后从头扫一遍这个哈希表,第一个没被填上的位置加1的那个数,就是第一个消失的数。

难就难在常数空间上,那题目没有指明不能修改原来的数组,我们能不能就地做一个hash呢?这个要保证个条件,原来位置上的数据不能轻易覆盖,因为如果像开hash表那样直接在对应位置上填数据的话,要么覆盖,要么置换,覆盖会出错,置换会提高整个算法的复杂度。聪明的你可能已经想到了,我们其实不需要在对应的位置上填上那个数,只要保证能区分出一个数在不在他对应的位置上,因此只要正负就可以了。

原来的负数怎么处理?负数肯定不符合要求,只要让他们变成正的,又不会影响我们的结果就好,统一变成n+2是不错的选择。现在,数组中的所有数据都是正的了,如果遇到一个大于等于n+1的数,可以直接略过,他们要么是负数变来的,要么一开始就太大,不是我们考虑的范围。如果遇到一个小于n+1的数据,我们可以知道他应该在的位置(A[i]-1),只要把这个位置标记为负的,就可以知道这个数呆在了它应该的位置上了。发现我们并没有改变原来那个位置上数的数值,它可以继续发挥作用。只不过每次判断的时候要加个abs而已。

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        for(int i=0;i<n;i++){
            if(A[i]<=0)
                A[i] = n+2;
        }
        for(int i=0;i<n;i++){
            if(abs(A[i])<n+1){
                int cur = abs(A[i])-1;
                A[cur] = -abs(A[cur]);
            }
        }
        for(int i=0;i<n;i++){
            if(A[i]>0)
                return i+1;
        }
        return n+1;
    }
};


leetcode第一刷_ First Missing Positive,布布扣,bubuko.com

leetcode第一刷_ First Missing Positive

标签:c++   leetcode   算法   

原文地址:http://blog.csdn.net/u012792219/article/details/25742657

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!