LeetCode 刷题记录 41. First Missing Positive

题目:
Given an unsorted integer array, find the smallest missing positive integer.

Example 1:

Input: [1,2,0]
Output: 3
Example 2:

Input: [3,4,-1,1]
Output: 2
Example 3:

Input: [7,8,9,11,12]
Output: 1
Note:

Your algorithm should run in O(n) time and uses constant extra space.

解法1:
不考虑空间复杂度,用set将所有的正数存进去,找到最大值,从1开始到最大值依次找,如果set中没有,即为首个缺失的正数,遍历完成后,说明缺失的正数是最大值加1
c++:

class Solution {
public:
    int firstMissingPositive(vector& nums) {
        int maxNum = 0;
        unordered_set s;
        for(int num : nums){
            if(num > 0){
                s.insert(num);
                maxNum = max(maxNum, num);
            }
        }
        for(int i = 1; i <= maxNum; ++i){
            if(!s.count(i)) return i;
        }
        return maxNum + 1;
    }
};

解法2:
桶排序
考虑到时间复杂度O(n)不能用常规排序,由于不能用额外空间,即空间复杂度为O(1),即我们要利用原来的数组
考虑桶排序,即nums[0]放1,nums[1]放2,即需要把nums[i]放在nums[nums[i] - 1]上,怎么实现呢

  1. 如果nums[i] != nums[nums[i]-1]),我们就一直交换 swap(nums[i] ,nums[nums[i]-1])
  2. 为了不数组越界,我们必须要限定条件,我们只处理正数,nums[i] > 0,另外nums[i]-1<=(n-1),n为数组长度,即nums[i] <= n
    处理完成后,我们再次遍历数组,如果那个位置不对,即为消失的正数,遍历完成后如果没有返回n+1

例:
Input: [3,4,-1,1]
Output: 2

第一次:num[i] = 3,它不应该在0号位置,而应该在2号位置,即第三个数,交换nums[i] ,nums[nums[i]-1],结果-1,4,3,1
继续循环,num[i] = -1,退出循环
第二次:num[i] = 4,它不应该在1号位置,而应该在3号位置,即第4个数,交换nums[i] ,nums[nums[i]-1],结果-1,1,3,4
继续循环,num[i] = 1,它不应该在1号位置,而应该在0号位置,即第1个数,交换nums[i] ,nums[nums[i]-1],结果1,-1,3,4
继续循环,num[i] = -1,退出循环
第三次:num[i] = 3,它的位置正确,退出循环
第四次:num[i] = 4,它的位置正确,退出循环
再一次遍历数组,即可找到缺失的2
Input: [7,8,9,11,12]
Output: 1
第一次:num[i] = 7,它不应该在0号位置,而应该在6号位置,即第7个数,但是数组没有这么大,不作处理
剩下的情况类似都是不作处理
再一次遍历数组,即可找到缺失的1

c++:

class Solution {
public:
    int firstMissingPositive(vector& nums) {
        int n = nums.size();
        for(int i = 0; i < n; i++){
            while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1]){
                swap(nums[i] ,nums[nums[i]-1]);
            }
        }
        for(int i = 0; i < n; ++i){
            
            if(nums[i] != (i + 1)) return i + 1;
        }
        return n + 1;
    }
};

java:
注意java中没有swap函数,需要我们自己写,另外java是值传递,所以我们要传三个参数进去

private void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

另外一种不用临时变量的写法

private void swap(int[] nums, int i, int j){
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        for(int i = 0; i < n; i++){
            while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1]){
                swap(nums, i ,nums[i]-1);
            }
            
        }
        
        for(int i = 0; i < n; ++i){
            
            if(nums[i] != (i + 1)) return i + 1;
        }
        return n + 1;
    
    }
    private void swap(int[] nums, int i, int j){
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
    // private void swap(int[] nums, int i, int j){
    //     int temp = nums[i];
    //     nums[i] = nums[j];
    //     nums[j] = temp;
    // }
}

python:
注意不能用nums[i] ,nums[nums[i]-1] = nums[nums[i]-1], nums[i]
首先会生成nums[nums[i]-1], nums[i],然后将nums[nums[i]-1]赋给nums[i] ,然后将nums[i]赋给,nums[nums[i]-1],但在第一次赋值的过程中nums[i] 的值就变了,导致错误

class Solution(object):
    def firstMissingPositive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        for i in xrange(n):
            while nums[i] > 0 and nums[i] <= n and nums[i] != nums[nums[i]-1]:
                tmp = nums[i]-1
                #nums[i] ,nums[nums[i]-1] = nums[nums[i]-1], nums[i]
                nums[i] ,nums[tmp] = nums[tmp], nums[i]
            #print nums
            
            
        
        
        for i in xrange(n):
            
            if nums[i] != (i + 1): return i + 1
        
        return n + 1

你可能感兴趣的:(LeetCode)