普通数组-----缺失的第一个正数

🔥个人主页: Milestone-里程碑

❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>

<<Git>><<MySQL>>

🌟心向往之行必能至

题目解析

这道题要求在一个未排序的整数数组中,找出没有出现的最小正整数,并且需要满足两个严格的条件:

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)(常数级额外空间)

直接排序或使用哈希表的方法,要么时间复杂度不达标,要么空间复杂度不达标。因此,我们需要采用一种巧妙的原地置换策略,利用数组本身作为哈希表来解决问题。

核心思路

对于一个长度为 n 的数组,缺失的最小正整数只可能在 [1, n+1] 范围内:

  • 如果 [1, n] 内的所有整数都出现了,那么缺失的就是 n+1
  • 否则,缺失的就是 [1, n] 中第一个未出现的数。

我们的目标就是把数组中所有在 [1, n] 范围内的数,放到它们 "应该" 在的位置上,即数值 k 应该放在索引 k-1 的位置上。这样,我们只需要遍历一次数组,找到第一个位置 i 上的数不等于 i+1i+1 就是我们要找的答案。

详细步骤

  1. 原地置换 :遍历数组,对于每个元素 nums[i],如果它是一个在 [1, n] 范围内的正整数,并且它没有在正确的位置 nums[i]-1 上,就将它与 nums[nums[i]-1] 交换,直到当前位置的元素正确或超出范围为止。
  2. 查找缺失 :再次遍历数组,检查每个位置 i。如果 nums[i] != i+1,说明 i+1 就是缺失的最小正整数。
  3. 全包含 :如果遍历结束后所有位置都正确,说明 [1, n] 都存在,返回 n+1

完整代码

cpp

复制代码
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        // 第一步:原地置换,将[1, n]范围内的数放到正确位置
        for (int i = 0; i < n; ++i) {
            // 当nums[i]在[1, n]范围内,且不在正确位置时,进行交换
            while (1 <= nums[i] && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
                int j = nums[i] - 1; // 计算正确的位置索引
                swap(nums[i], nums[j]); // 交换到正确位置
            }
        }
        
        // 第二步:遍历查找第一个缺失的正整数
        for (int i = 0; i < n; ++i) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        
        // 如果[1, n]都存在,返回n+1
        return n + 1;
    }
};

复杂度分析

  • 时间复杂度 :O(n)
    • 虽然有两层循环,但每个元素最多被交换到其正确的位置一次,因此总的交换次数是 O (n)。两次线性遍历也是 O (n),所以整体时间复杂度为 O (n)。
  • 空间复杂度 :O(1)
    • 我们只在原数组上进行操作,没有使用额外的辅助空间,满足了常数级空间复杂度的要求。

示例演示

nums = [3, 4, -1, 1] 为例:

  1. 初始数组:[3, 4, -1, 1]
  2. 处理 i=0nums[0]=3,应在位置 2,交换后数组变为 [-1, 4, 3, 1]
  3. 处理 i=1nums[1]=4,应在位置 3,交换后数组变为 [-1, 1, 3, 4]
  4. 处理 i=1nums[1]=1,应在位置 0,交换后数组变为 [1, -1, 3, 4]
  5. 处理 i=2nums[2]=3,已在正确位置;i=3nums[3]=4,已在正确位置。
  6. 最终数组:[1, -1, 3, 4]
  7. 遍历查找,发现 i=1nums[1] != 2,所以返回 2
相关推荐
春日见7 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
寻寻觅觅☆7 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子8 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
2013编程爱好者8 小时前
【C++】树的基础
数据结构·二叉树··二叉树的遍历
NEXT068 小时前
二叉搜索树(BST)
前端·数据结构·面试
化学在逃硬闯CS8 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar1239 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS9 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗9 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
Elastic 中国社区官方博客9 小时前
如何防御你的 RAG 系统免受上下文投毒攻击
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索