leetcode41缺失的第一个正数(困难)

leetcode41缺失的第一个正数
要求:给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
时间复杂度:o(n)
空间复杂度:o(1)
很多人觉得这题简单,不应该放在困难区,其实大多数都没有考虑时间复杂度和空间复杂度,其实很多算法题一模一样,只不过对时间复杂度做下要求,难度瞬间提升不少,解决这题需要用到桶排序类似的算法,其实和之前我说select模型的位图差不多是一个概念,这种算法太巧妙了,我刚开始接触的时候真的被惊到了。
例如:3,1,4,5
输出:2
解法:如果我们可以用某种算法将3 1 4 5排成1 5 3 4(即1放在第一个位置,3放在第三个位置,4放在第四个位置,5之能被放在第二个位置了),我们就可以很容易找出缺失的第一个正数是2
下面我们来看看这个算法的运行过程
3,1,4,5
数组长度为4
第一步i=0
a[i]=3, 把3放在第三个位置即i=2的位置,交换3和4
4,1,3,5
只要执行了交换操作,i就不自增

第二步i=0
a[i]=4,把4放在第四个位置即i=3的位置,交换4和5
5,1,3,4
只要执行了交换操作,i就不自增

第三步i=0
5>数组长度4,所以不能把5放在第五个位置,不能交换i++

第四步i=1
5,1,3,4
a[1] =1,把1放在数组第一个位置,即下标为0的位置,5和1交换
1,5,3,4
第五步i=1
a[1]=5,不能交换,i++
第六步i=2
a[2]=3,3已经在合适的位置了,不能交换,i++
第七步i=3
a[3]=4,4已经在合适的位置了,不能交换,i++

public int firstMissingPositive(int[] nums) {
        int len = nums.length;
        if(null==nums||len==0)return 1;
        //数据预处理 桶排序处理数据
        for(int i=0;i<len;){
            int cur = nums[i];
            //满足这四个条件才可以交换
            if(cur!=i+1&&cur<=len&&cur>0&&cur!=nums[cur-1]){
                //交换 i和cur-1
                nums[i] = nums[cur-1];
                nums[cur-1] = cur;
            }else{
                ++i;
            }
        }
        //找最小正数
        for(int i=0;i<len;++i){
            if(i+1!=nums[i]){
                return i+1;
            }
        }
        // 1 2 3 4这种情况
        return len+1;
    }

你可能感兴趣的:(算法数据结构)