LeetCode题目41:缺失的第一个正数

本文详细介绍了如何用三种方法解决LeetCode题目41,包括使用索引作为哈希键、排序后线性扫描和哈希表,分析了每种方法的时间复杂度和空间复杂度,以及各自的优缺点。
摘要由CSDN通过智能技术生成

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

LeetCode题目41“缺失的第一个正数”要求在未排序的整数数组中找出最小的未出现的正整数。本文将详细介绍三种解决这一问题的方法,包括解题思路、详细的代码实现以及算法分析。

题目描述

输入:一个未排序的整数数组 nums

输出:未在数组中出现的最小正整数。

示例

输入: [1,2,0]
输出: 3
输入: [3,4,-1,1]
输出: 2
输入: [7,8,9,11,12]
输出: 1

方法一:索引作为哈希键

解题步骤

  1. 处理负数和零:由于我们只关心正数,可以先将所有非正整数替换为一个大于数组长度的值(例如 n+1,其中 n 是数组长度)。
  2. 利用索引标记:遍历数组,使用数组索引作为哈希键来标记存在的数字。具体操作是,对于每个数字 x,如果 1 <= x <= n,则将索引 x-1 的位置的数字设置为负数。
  3. 寻找结果:再次遍历数组,第一个索引位置 i 使得 nums[i] > 0i + 1 就是缺失的最小正数。

代码示例

def firstMissingPositive(nums):
    n = len(nums)
    # 将所有的负数和零替换为n+1,n+1是一个不可能出现在合法输出中的数字
    for i in range(n):
        if nums[i] <= 0:
            nums[i] = n + 1
            
    # 使用数组索引作为哈希键,通过置负标记存在的数字
    for i in range(n):
        num = abs(nums[i])
        if num <= n:
            nums[num - 1] = -abs(nums[num - 1])
    
    # 寻找第一个大于0的索引位置,即是缺失的最小正数
    for i in range(n):
        if nums[i]> 0:
            return i + 1

    # 如果数组中包含了1到n的所有数字,则缺失的第一个正数是n+1
    return n + 1

# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1

算法分析

  • 时间复杂度:O(N),其中 N 是数组长度。算法涉及几个线性扫描,每个扫描的时间复杂度都是O(N)。
  • 空间复杂度:O(1)。除了输入数组外,没有使用额外的空间,所有操作均在原数组上进行。

方法二:排序后线性扫描

解题步骤

  1. 排序数组:首先对数组进行排序。
  2. 线性扫描:遍历排序后的数组,查找第一个缺失的最小正数。

代码示例

def firstMissingPositive(nums):
    nums.sort()
    target = 1
    for num in nums:
        if num == target:
            target += 1
    return target

# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1

算法分析

  • 时间复杂度:O(N log N),主要时间开销来源于排序。
  • 空间复杂度:O(1) 或 O(N),这取决于使用的排序算法。

方法三:使用哈希表

解题步骤

  1. 使用哈希表存储:将所有正数存储在哈希表中。
  2. 寻找最小正数:从 1 开始递增寻找不在哈希表中的最小正数。

代码示例

def firstMissingPositive(nums):
    num_set = set(nums)
    target = 1
    while target in num_set:
        target += 1
    return target

# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1

算法分析

  • 时间复杂度:O(N),虽然使用了哈希表,但构建哈希表和查询的总时间仍是线性的。
  • 空间复杂度:O(N),需要额外的空间来存储哈希表。

总结

为了直观地比较解决LeetCode题目41 "缺失的第一个正数"的三种方法,下面的表格将展示它们在不同技术维度的性能和特点,包括时间复杂度、空间复杂度以及各自的优势和劣势。

特征方法一:索引作为哈希键方法二:排序后线性扫描方法三:使用哈希表
时间复杂度O(N)O(N log N)O(N)
空间复杂度O(1)O(1) 或 O(N)O(N)
优势- 不使用额外空间
- 快速且高效
- 直接在原数组上操作,不需要额外的数据结构
- 实现简单
- 直观易理解
- 适用于不限制时间复杂度的场景
- 实现简单
- 查找速度快
- 直接使用Python内置数据结构
劣势- 算法理解相对复杂
- 需要修改原数组作为标记
- 时间复杂度较高,尤其是在数据量大时
- 空间复杂度依赖于排序算法
- 空间开销大
- 需要额外空间存储所有正数
适用场景- 数据量大且对空间有严格限制时
- 需要在原地解决问题时
- 数据预处理和排序成本低时
- 对算法执行时间要求不严格时
- 空间充足时
- 需要快速实现和简洁代码时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据分析螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值