【leetcode】41 缺失的第一个正数(数组,哈希映射)

题目链接:https://leetcode-cn.com/problems/first-missing-positive/

题目描述

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

示例 1:

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

示例 2:

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

示例 3:

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

说明:

你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。

思路

首先我们确定一个事实:缺失的第一个正数必定在(1,n)之间;
我们考虑hash表映射的方法:

  • 假设原始数组为 A。先构造一个临时数组 tmp,初始化为 0,大小为A.size(). 遍历 A,把 A[i] 复制到 tmp[A[i]-1] 的位置。如果 A[i] - 1 超过了 tmp 的范围,就直接扔掉。如此一来,tmp[0…size) 中就保存了一部分 A 的值。然后从位置 0 开始检查 tmp,如果发现该位置的值和索引号不匹配,就说明找到了缺失的数了。

注意上面的方案需要额外空间,我们考虑原地算法,直接在原始数组中操作,把每个数放到正确的位置。采用座位交换法

(1)从第一个位置开始,如果nums[i] > 0 && nums[i] <= nums.size(),则不断地交换num[i]nums[nums[i] -1],直到 nums[nums[i]] - 1] = i
(2)对第二个位置到第n个位置做相同操作

复杂度分析

  • 时间复杂度:O(n)。在交换的过程中最多判断2n次,遍历验证的过程最多n次,总共最多3n次。
  • 空间复杂度:O(1)

代码

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {

        // 把num[i]放到nums[i]-1的位置上;最多循环内最多2n次
        for (int i = 0; i < nums.size(); ++i) {
            // 最后的条件保证不重复交换
            while (nums[i] > 0 && nums[i] <= nums.size() && nums[i] != nums[nums[i]-1])
                swap(nums[i], nums[nums[i] -1]);
        }
        for (int i = 0; i < nums.size(); ++i) {
            if(nums[i]!=i+1)
                return i+1;
        }
        return nums.size()+1;
    }
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值