LeetCode 41. 缺失的第一个正数 原地哈希 Java实现

41. 缺失的第一个正数

题目来源

41. 缺失的第一个正数

题目分析

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

题目难度

  • 难度:困难

题目标签

  • 标签:数组、哈希表

题目限制

  • 1 <= nums.length <= 5 * 10^5
  • -2^31 <= nums[i] <= 2^31 - 1

解题思路

思路1:数组记录法

  1. 问题定义
    • 需要找到数组 nums 中没有出现的最小的正整数。
  2. 核心算法
    • 创建一个长度为 n+1 的数组 a,用于记录 1n 之间每个数字是否出现。
    • 遍历 nums,将出现过的正整数标记在数组 a 中。
    • 再次遍历数组 a,找到第一个未标记的位置,即为缺失的最小正整数。

思路2:哈希表思想

  1. 问题定义
    • 利用原数组 nums 作为哈希表,通过交换元素的方式,将每个数字放到其对应的索引位置上。
  2. 核心算法
    • 遍历数组,找到第一个索引位置上的数字不等于索引加一的元素,即为缺失的最小正整数。

核心算法步骤

方法1:数组记录法
  1. 初始化一个长度为 n+1 的数组 a
  2. 遍历 nums,标记出现过的正整数。
  3. 遍历数组 a,找到第一个未标记的位置。
方法2:哈希表思想
  1. 遍历 nums,将每个数字放到其对应的索引位置上。
  2. 遍历数组,找到第一个索引位置上的数字不等于索引加一的元素。

代码实现

以下是两种方法的 Java 代码实现:

public int firstMissingPositive(int[] nums) {
    int n = nums.length;
    int[] a = new int[n + 1];
    for (int num : nums) {
        if (num > 0 && num <= n) {
            a[num] = 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (a[i] == 0) {
            return i;
        }
    }
    return n + 1;
}
public int firstMissingPositive2(int[] nums) {
    int n = nums.length;
    for (int i = 0; i < n; i++) {
        while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
            int temp = nums[nums[i] - 1];
            nums[nums[i] - 1] = nums[i];
            nums[i] = temp;
        }
    }
    for (int i = 0; i < n; i++) {
        if (nums[i] != i + 1) {
            return i + 1;
        }
    }
    return n + 1;
}

代码解读

  • 方法1:通过创建一个额外数组来记录每个数字是否出现。
  • 方法2:通过在原数组上交换元素,将每个数字放到其正确的位置上。

性能分析

  • 时间复杂度
    • 方法1:O(n),因为我们需要遍历两次数组。
    • 方法2:O(n),尽管内部有一个 while 循环,但每个数字最多只会被交换一次。
  • 空间复杂度
    • 方法1:O(n),我们需要一个长度为 n+1 的额外数组。
    • 方法2:O(1),我们只使用了常数级别的额外空间。

测试用例

public static void main(String[] args) {
    int[] nums = {3, 4, -1, 1};
    System.out.println(firstMissingPositive(nums)); // 输出: 2
    System.out.println(firstMissingPositive2(nums)); // 输出: 2
    int[] nums2 = {1, 2, 0};
    System.out.println(firstMissingPositive(nums2)); // 输出: 3
    System.out.println(firstMissingPositive2(nums2)); // 输出: 3
}

扩展讨论

有没有其他方法?
  • 排序法:首先对数组进行排序,然后遍历排序后的数组,找到第一个不满足 nums[i] == i + 1 的位置。这种方法的时间复杂度取决于排序算法,通常是 O(n log n)
原地哈希法
  • 说明:方法2实际上是一种原地哈希的方法,它通过交换元素来将数字放置到其对应的索引位置上,从而避免了使用额外的空间。

总结

本题通过两种不同的方法来寻找缺失的第一个正数。方法1使用了一个额外的数组来记录出现过的数字,而方法2则利用了原地哈希的思想,通过交换元素来达到目的。两种方法各有优劣,方法1在空间上占用更多,但实现简单;方法2在空间上更优,但实现上稍微复杂一些。在实际应用中,可以根据题目对时间和空间的要求来选择合适的方法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值