【题解】41. 缺失的第一个正数(数组、哈希表)

https://leetcode.cn/problems/first-missing-positive/description/?envType=study-plan-v2&envId=top-100-liked
在这里插入图片描述

  • 方法1:
    直接使用哈希表存储,再逐个寻找没有出现的最小正整数,时间复杂度为 O(n), 空间复杂度为 O(n);
class Solution {
    
    
public:
    int firstMissingPositive(vector<int>& nums) {
    
    
        unordered_set<int> count_set;
        for (auto& num : nums) {
    
    
            count_set.insert(num);
        }
        for (int i = 1; i < INT_MAX; ++i) {
    
    
            if (!count_set.count(i)) {
    
    
                return i;
            }
        }
        return -1;
    }
};
  • 方法2:原地哈希

利用数组的索引作为哈希表的位置,将每个元素放置到其对应的索引位置。这样,我们可以在原地进行操作,不需要额外的空间。

class Solution {
    
    
public:
    int firstMissingPositive(vector<int>& nums) {
    
    
        int n = nums.size();

        // 将负数和大于n的数置为n+1(这些数不影响结果)
        for (int& num : nums) {
    
    
            if (num <= 0 || num > n) {
    
    
                num = n + 1;
            }
        }

        // 标记出现过的数字为负数
        for (int i = 0; i < n; ++i) {
    
    
            int num = abs(nums[i]);
            if (num <= n) {
    
    
                nums[num - 1] = -abs(nums[num - 1]);
            }
        }

        // 查找第一个未标记的索引
        for (int i = 0; i < n; ++i) {
    
    
            if (nums[i] > 0) {
    
    
                return i + 1;
            }
        }

        // 如果所有的 1 到 n 都出现了,则返回 n+1
        return n + 1;

    }
};

解释:

  1. 预处理:将数组中所有负数和大于 n 的数标记为 n + 1,因为这些数不会影响到最小缺失正整数的结果。
  2. 标记:遍历数组,将每个出现的数字的对应位置标记为负数(使用绝对值),以表示该数字出现过。
  3. 查找:再次遍历数组,查找第一个未被标记的位置,返回 i + 1 作为结果。如果所有位置都被标记过,返回 n + 1

复杂度:

  • 时间复杂度:O(n) —— 由于只进行了一次遍历来标记,和一次遍历来查找结果。
  • 空间复杂度:O(1) —— 除了输入数组外没有使用额外空间。

猜你喜欢

转载自blog.csdn.net/Colorful___/article/details/141534763