leetcode第一刷_ First Missing Positive

143 篇文章 0 订阅

未排序数组,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;
    }
};


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值