41. 缺失的第一个正数

1,222 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

题目描述

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

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

image.png

思路分析

如果是不考虑O(n)时间复杂度的话,我们可以通过排序来解决,如果不考虑常数级别空间复杂度,我们也可以将元素扔入单调栈或堆中,但是在目前的要求下就不能使用以上方案了。

不过这些方案有一些共同点,其实或有或无的想去排序,也很好理解,我们可以通过排序更容易的找到最小的正数。

这道题本身也有个条件,我们假设对于元素,只存在0-n,去找到缺失的最小的正数(因为有0,所以必存在最小的正数或n+1)。

那如果元素不是0-n,说明结果必然在0-n中,所以我们只需要对元素大小为0-n的元素进行排序即可。

大多数排序很难O(n)时间复杂度,是因为结果集并不是有限制的,但是在结果集限制的条件下,我们可以通过交换排序,实现一种O(n)时间复杂度的排序。

具体实现

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

总结

这道题本身难度并不是很大,只能说交换这种思路不好想,不过只要做过一次就没问题了。