Leetcode 41 First Missing Positive

在这里插入图片描述
思路一: O(n)时间复杂度, O(n)空间复杂度。这是我自己思路,利用set。因为数组中重复的数和小于等于0的数都是没用的。那么我们只需要将大于0的数放进set中。接着我们数一下set中有几个数字,假设有5个数字,那么我们就该从1check到5,看set中有没有,没有的话就直接返回就行,就是最后的答案,如果都有的话那就返回6(5+1)。不难想,直接上代码:

class Solution {
    public int firstMissingPositive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for(int num : nums){
            if(num > 0){
                set.add(num);
            }
        }
        int size = set.size();
        for(int i = 1; i <= size; ++i){
            if(!set.contains(i)){
                return i;
            }
        }
        return size + 1;
    }
}

**思路二:**这也是lc的解答,这个时间复杂度还是O(n),但是空间复杂度是O(1),不需要额外存储空间。他巧妙的用正负号来表示数字是否出现过,感觉挺难讲清楚的,是一个比较巧妙的方法,不过我并不expect我在面试中可以想到这种方法,所以就当了解一下就好了,具体思路可以看了lc解答,看完了就发现也挺简单的,就是太巧妙了,很难想到。下面直接上代码:

class Solution {
    public int firstMissingPositive(int[] nums) {
        int len = nums.length;
        
        // 判断数组中是否有1,因为后面要将一些数替换成1,所以这步必须有
        boolean flag = false;
        for(int num : nums){
            if(num == 1){
                flag = true;
                break;
            }
        }
        if(flag == false){
            return 1;
        }
        
        // 替换成1
        for(int i = 0; i < len; ++i){
            if(nums[i] <= 0 || nums[i] > len){
                nums[i] = 1;
            }
        }
        
        // traverse数组,通过改变符号来表明数字(下标)是否出现过,这边很巧妙的利用了下标。负号代表出现过。
        for(int i = 0; i < len; ++i){
            int a = Math.abs(nums[i]); 
            if(a == len){
                nums[0] = -Math.abs(nums[0]);
            }else{
                nums[a] = -Math.abs(nums[a]);
            }
        }
        
        // 返回第一个是正数的下标,就是答案
        for(int i = 1; i < len; ++i){
            if(nums[i] > 0){
                return i;
            }
        }
        
        // 下标0用来标记数字len是否出现过的,len为可能的最大的正数
        if(nums[0] > 0){
            return len;
        }
        
        // 数组包含从1开始到len的所有正数,那么就不存在missing了,所以返回len + 1
        return len + 1;
    }
}

总结: 无

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值