LeetCode Java缺失的第一个整数(原地哈希)

官方给的题解我自己感觉有点难理解,按照以下思路能更好理解些。

缺失的第一个整数

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

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

示例 1:

输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:

输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1

什么是原地哈希?

原地哈希(In-place Hashing)是一种在有限空间内处理数据的算法技术,通常用于在不使用额外存储空间的情况下对数据进行哈希操作。这种方法在内存受限的环境中非常有用,例如嵌入式系统或实时数据处理。

核心思想

原地哈希的核心思想是通过修改原始数据本身来实现哈希操作,而不是创建新的数据结构来存储哈希结果。这样可以节省内存空间,但可能会改变原始数据。

应用场景

  1. 去重:在数组中去除重复元素。

  2. 查找:快速查找特定元素。

  3. 排序:通过哈希值对数据进行排序。

实现方式

  1. 数组索引作为哈希键:利用数组的索引作为哈希键,将元素值映射到对应位置。

  2. 交换元素:通过交换元素位置,将元素放置到其哈希值对应的索引处。

示例

假设有一个数组 [4, 3, 2, 7, 8, 2, 3, 1],我们希望去除重复元素并保留唯一元素。

  1. 初始化:遍历数组,使用数组索引作为哈希键。

  2. 哈希映射:将每个元素映射到其值对应的索引位置。

  3. 去重:如果发现重复元素,则跳过或标记。

最终,数组可能变为 [1, 2, 3, 4, 7, 8],去除了重复元素。

优点

  • 节省空间:不需要额外存储空间。

  • 高效:通常具有较高的时间效率。

缺点

  • 数据修改:原始数据会被改变。

  • 复杂度:实现可能较为复杂,需处理冲突和边界情况。

代码

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;

        // 将每个正整数放到正确的位置上
        for (int i = 0; i < n; i++) {
            // 当 nums[i] 在 [1, n] 范围内,并且 nums[i] 不在正确的位置上时,进行交换
            while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
                swap(nums, i, nums[i] - 1);
            }
        }

        // 找到第一个不满足 nums[i] == i + 1 的位置
        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }

        // 如果所有位置都满足条件,则返回 n + 1
        return n + 1;
    }

    // 交换数组中两个元素的位置
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

代码思路

  1. 核心思想

    • 将数组中的每个正整数 nums[i] 放到它应该在的位置上,即 nums[i] 应该放在索引 nums[i] - 1 处。

    • 最终遍历数组,找到第一个不满足 nums[i] == i + 1 的位置,即为缺失的最小正整数。

  2. 具体步骤

    • 遍历数组:对于每个元素 nums[i],如果它在 [1, n] 范围内(n 是数组长度),并且它不在正确的位置上(即 nums[nums[i] - 1] != nums[i]),则将其交换到正确的位置。

    • 查找缺失的正整数:遍历数组,找到第一个不满足 nums[i] == i + 1 的位置,返回 i + 1。如果所有位置都满足条件,则返回 n + 1

  3. 交换操作

    • 通过 swap 函数交换数组中的两个元素。


代码分析

  1. 时间复杂度

    • 虽然代码中有嵌套的 while 循环,但每个元素最多只会被交换一次,因此总的时间复杂度为 O(n)

  2. 空间复杂度

    • 只使用了常数级别的额外空间(交换时的临时变量),因此空间复杂度为 O(1)

  3. 原地修改

    • 代码直接修改了原始数组 nums,没有使用额外的数据结构,符合原地哈希的思想。

  4. 边界条件

    • 如果数组为空,返回 1

    • 如果数组包含所有正整数 [1, 2, ..., n],则返回 n + 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值