leetcode题解-41. First Missing Positive

题目:

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],
[2],
[-1,1],
[-1,1000],
[-1,1,1,1,2,22]

即可能两个数字之间差别很大,也可能会有重复数字出现。我看到题目的第一反应,是将其进行排序,这样可以很方便的找到丢失的正数。但是中间就遇到了这些边界情况,搞得跳了好几次。其实排序之后我们需要做的就是遍历数组,找到大于零且比前面一个正数大超过一的数字。代码入下:

    public int firstMissingPositive(int[] nums) {
        if(nums.length == 0 || nums == null)
            return 1;
        Arrays.sort(nums);
        for(int i=0; i<nums.length; i++){
            if(nums[i] > 0)
                if(nums[i] != 1)
                    return 1;
                else{
                    //判断是否为突变点,并且排除相等的情况
                    while(i < nums.length-1 && (nums[i+1] == nums[i]+1 || nums[i+1] == nums[i]))
                        i++;
                    return nums[i]+1;
                }
        }
        return nums[nums.length-1]+1;
    }

看到题目的同时,脑海中还有另外一种解法,那就是使用一个数组来保存遍历过的正数,这样有一个问题,比如说[-1, 1000]这种情况下,我们申请的数组不够大怎么办,后来一想,如果出现了这种情况,那说明丢失的数字肯定在这之前。也就是说,我们原本的数组大小就足以支撑,只不过需要加一个限制条件,当某个元素大于数组长度时,不要把它保存到数组当中即可。代码入下:

    public int firstMissingPositive1(int[] nums) {
        int n = nums.length;
        //该数组用于记录原数组信息,下标记录原数组的值
        int[] tmp = new int[n+2];

        for(int i=0; i<n; i++){
            if(nums[i] > 0 && nums[i] < n+2){
                tmp[nums[i]] = 1;
            }
        }
        for(int i=1; i<n+2; i++)
            if(tmp[i] != 1)
                return i;

        return 1;
    }

但是题目要求我们需要使用常数的存储空间。所以我们应该使用数组内部交换来实现,代码入下:

    public int firstMissingPositive2(int[] A) {
        int i = 0;
        while(i < A.length){
            if(A[i] == i+1 || A[i] <= 0 || A[i] > A.length) i++;
            else if(A[A[i]-1] != A[i]) swap(A, i, A[i]-1);
            else i++;
        }
        i = 0;
        while(i < A.length && A[i] == i+1) i++;
        return i+1;
    }

    private void swap(int[] A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值