每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive

2020年6月27日 缺失的第一个正数 firstMissingPositive

每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第1张图片
默认格式:

class Solution {
    public int firstMissingPositive(int[] nums) {

    }
}

解题思路:

如果不考虑限制条件,能够直接先排序然后寻找从1开始第一个没有出现的值,那个值就是最小没有出现的正整数。这样的时间复杂度是O(nlogn)。

如果要控制时间复杂度,可以把每个大于0的值都存到哈希表中,然后遍历这个哈希表,寻找第一个没有出现的值,这样的时间复杂度是O(n)但是空间复杂度就是O(n)了,也不符合题目中的要求。

那么如果不允许这么做,我们能做的只有找到缺失位置和没有排序数字之间的关系。

应该有那么几个关键位置能够记录。

在想这道题的时候,我产生了一个疑惑,他给我传入了一个数组,我不新建数组,就在原数组的地址上该值,属不属于额外空间。然后我去查阅了资料,资料上说不属于额外空间,那么意味着我之前的方向是错误的,所谓的不使用额外的空间,我们可以利用传入的数组来存我们的值。

最小的缺失正数和数组有如下的关系。

最小缺失正数必定小于数组长度-1。因为只有在数组的所有值都是从1开始连续的正整数,才会出现最小缺失的正整数是长度+1的情况。

那么我们遍历一遍数组,将每个数插入到他应该存在的位置,比如把2插入到下标1的位置,5插入到下标4的位置。

如果数字超过长度或者小于等于0,则不处理直接记为0。

处理结束后,遍历一遍数组,找到第一个值为0的位置。

图示:
每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第2张图片

第一个数字3,把他移动到数组的第三个位置上,并且把第三个数字上的值移动过来。

每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第3张图片
重复上面的过程,把6移动到属于他的第六个位置,把第六个位置上的值移动回来。

每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第4张图片

继续重复。
每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第5张图片

在这里插入图片描述
1和本身相等,所以直接跳过,同理,2,3也跳过

-2小于我们的范围,直接置为0,然后移动4。
每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第6张图片

最后遍历数组,找到第一个0,也就是5所在的位置。

每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第7张图片

代码部分:

少考虑了一个问题,如果两个值按上面的规则重复的话,就会产生死循环。

    public int firstMissingPositive(int[] nums) {

        //遍历数组,处理数组
        for (int i=0;i<nums.length;){

            //如果已经处理好了,处理下一个
            if (nums[i]==i+1){
                i++;
            }else
            {
                //如果值在范围内
                if (nums[i]<=nums.length&&nums[i]>0){

                    int val=nums[i];

                    //把目标为止的值移过来
                    nums[i]=nums[nums[i]-1];

                    //下标为i的值赋值为i+1
                    nums[val-1]=val;

                }
                //如果在范围外,直接置为0,并且处理下一个
                else {
                    nums[i]=0;
                    i++;
                }
            }

        }

        //遍历处理完成的数组,找到第一个没有出现的正数
        for (int i=0;i<nums.length;i++){
            if (nums[i]==0)
                return i+1;
        }

        //如果全都存在,那么返回长度+1的值
        return nums.length+1;
    }

在移动两个参数时增加了一个判断,用来重复的时候进行处理。

//如果值重复了,将后面的那个值删掉
if (val==nums[i]){
    nums[i]=0;
}

每日一题算法:2020年6月27日 缺失的第一个正数 firstMissingPositive_第8张图片

你可能感兴趣的:(每日一题算法)