LeetCode 41

41. 缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?

示例 1:

输入:nums = [1,2,0]
输出:3

示例 2:

输入:nums = [3,4,-1,1]
输出:2

示例 3:

输入:nums = [7,8,9,11,12]
输出:1

提示:

0 <= nums.length <= 300
-231 <= nums[i] <= 231 - 1
class Solution {
    
    
    public int firstMissingPositive(int[] nums) {
    
    
        //1. 空间复杂度为n的方法: 建立一张长度为 nums.length+1 的'桶'表即可

        //2.使用原表记录数据,数字是否存在通过-号和下标判断。这样在记录数时不会改变未遍历的数 
        // 可以先将所有的负数初始化为1,初始化为0则无法取反存值(或者需要多出一步判断)
        // 取1不管在存数之前该位置有没有数据,都可以直接取反即可
        // 取数时 对数取绝对值Math.abs()
        // 设置为负时需要判断是否下标越界
        // 存数时判断:if < 0,则说明已经存过数了,不作操作,> 0 则对数取反(负)
        //  位置下标 == 数值 - 1
        // 先将数字1排除
        boolean flag = false; // 判断有没有1的标志
        for (int i = 0; i < nums.length; i++) {
    
    
            if (nums[i] == 1) {
    
    
                flag = true;
                break;
            } 
        }
        if (!flag) return 1;

        // 将所有的非正数设置为1
        for(int i = 0; i < nums.length; i++) {
    
    
            if (nums[i] <= 0) nums[i] = 1;
        } 
        // 同时应该将0下标处 取反,表示1是存在的
        nums[0] = -1 * nums[0];
        // 遍历元素,两种情况需要操作,|x| > 1
        for (int i = 0; i < nums.length; i++) {
    
    
            int x = nums[i];
            if ((x > 1) && (x <= nums.length)) {
    
     // 这里和下面的判断都强制重复赋值,省去了判断
                nums[x-1] = -1 * Math.abs(nums[x-1]);
            }
            if ((x < -1) && (-x <= nums.length)) {
    
     // 当前位置是已经被修改过一次的数
                nums[Math.abs(x) - 1] = -1 * Math.abs(nums[Math.abs(x) - 1]);
            }
            // 最后修改完判断:是不是恰巧修改了自己
            // if (x == nums[i] && x > 0 ) nums[i] = 1;  // 如果是>1的情况
            // 没有修改自己,也有可能是本身是负数
        }

        for (int i = 0; i < nums.length; i++) {
    
    
            if (nums[i] > 0) {
    
     // 如果某位置处为1,则说明存在 缺失
                return i+1;
            }
        }
        return nums.length + 1;

    }
}





猜你喜欢

转载自blog.csdn.net/mingrizhixin/article/details/114270338
今日推荐