数组作为哈希表的妙用:寻找缺失的第一个正数

news2025/3/27 8:20:43

数组作为哈希表的妙用:寻找缺失的第一个正数

大家好,我是Echo_Wish,今天我们来探讨一个经典的算法问题——“缺失的第一个正数”。听起来可能有点简单,但它实际上是一个非常有意思且富有挑战性的题目,在面试中常常会碰到。更重要的是,这个问题能够帮助我们更好地理解数组和哈希表的妙用,今天我们将通过实际的代码演示,看看如何高效解决这个问题。

问题描述

题目要求我们在一个无序整数数组中,找到缺失的第一个正整数。比如,给定数组 [1, 2, 0],缺失的第一个正整数是 3,因为数组中没有 3,而且 12 都在其中。

这个问题有一个关键点:我们不仅要找到缺失的正数,而且还要考虑高效性,让我们能够在 O(n) 的时间复杂度下解决问题。

思考与优化

一开始,我想到了一个直接的办法——使用哈希表。具体来说,我们可以把数组中的元素都记录到哈希表里,然后从 1 开始检查每个数字是否存在哈希表中。这样一来,查找每个元素的时间复杂度是 O(1),整体复杂度是 O(n),效率较高。

但问题在于:直接使用哈希表占用的空间较大。我们其实可以通过数组本身来模拟哈希表,从而降低空间复杂度。接下来,我们通过一个具体的方案来分析如何操作。

解决方案:用数组模拟哈希表

由于题目要求我们找到缺失的第一个正整数,我们知道正整数的范围是从 1 开始,一直到数组的长度 n。因此,我们可以通过将数组的每个元素与数组下标一一对应来实现模拟哈希表的功能。

解决步骤

  1. 过滤无效值
    由于我们只关心正整数 1n,任何小于 1 或大于 n 的值都不需要关心,因此我们可以直接将它们忽略。

  2. 将数组值放到正确的位置
    我们可以将每个元素放到它应该去的位置,比如数字 1 放到下标 0,数字 2 放到下标 1,依此类推。这样,当我们遍历数组时,所有值都应该出现在它们对应的下标位置。

  3. 找到缺失的正整数
    遍历一遍处理过的数组,找到第一个不在正确位置的值,那么它对应的下标就是缺失的第一个正整数。

代码实现

def first_missing_positive(nums):
    n = len(nums)
    
    # Step 1: 将无效值转换为n+1,表示这些值不参与计算
    for i in range(n):
        if nums[i] <= 0 or nums[i] > n:
            nums[i] = n + 1
    
    # Step 2: 将每个数字放到它对应的位置
    for i in range(n):
        val = abs(nums[i])
        if 1 <= val <= n:
            # 放置到正确的索引位置
            nums[val - 1] = -abs(nums[val - 1])  # 变成负值,表示已出现
    
    # Step 3: 找到第一个未被标记的位置
    for i in range(n):
        if nums[i] > 0:
            return i + 1  # 返回缺失的正整数
    
    # 如果所有位置都已经有值,说明缺失的正整数是n+1
    return n + 1

# 示例测试
nums = [1, 2, 0]
print(first_missing_positive(nums))  # 输出 3

nums = [3, 4, -1, 1]
print(first_missing_positive(nums))  # 输出 2

代码解析

  1. 过滤无效值
    我们通过遍历数组,将所有小于 1 或大于 n 的值替换成 n + 1,这是因为在我们的问题范围内,这些数字不可能是缺失的第一个正整数。

  2. 数组重排
    在第二步中,我们将每个数 x 放到下标 x-1 的位置,通过将其变成负数来标记它已经出现在数组中。这是模拟哈希表的一种方式,借助数组的空间和下标直接存储信息。

  3. 查找缺失的数字
    在最后一步,我们遍历数组,查找第一个正数,它的下标就是缺失的第一个正整数。

时间与空间复杂度分析

  • 时间复杂度:O(n),我们只需要遍历数组三次。
  • 空间复杂度:O(1),我们没有使用额外的哈希表,而是直接在原数组上进行了操作。

举个例子

让我们看一个具体的例子:

假设输入是 [3, 4, -1, 1],按照我们的思路,第一步过滤无效值,数组变成 [3, 4, 5, 1]。然后,我们将每个值放到它该在的位置。经过第二步处理后,数组变成 [-3, -4, 5, -1]。最后,我们遍历数组,发现位置 2 没有被标记(值为 5),因此缺失的第一个正整数是 2

总结

通过这个问题,我们不难发现,数组可以作为一种高效的哈希表,通过巧妙地利用下标来存储信息,可以大大减少空间复杂度。这种思路不仅适用于“缺失的第一个正数”问题,也能在其他类似的算法题中找到应用。希望这篇文章能够帮助你更好地理解如何在面试或实际项目中利用数组来优化算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2320754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

物化视图详解:数据库性能优化的利器

物化视图&#xff08;Materialized View&#xff09;作为数据库性能优化的核心手段&#xff0c;通过预计算和存储查询结果&#xff0c;显著提升了复杂查询的效率。本文将深入剖析物化视图的工作原理、应用场景及最佳实践&#xff0c;帮助企业在合适的场景中充分发挥其性能优势。…

蓝桥杯备考-》单词接龙

很明显&#xff0c;这道题是可以用DFS来做的&#xff0c;我们直接暴力搜索&#xff0c;但是这里有很多点是我们需要注意的。 1.我们如何确定两个单词能接上&#xff1f; 比如touch和choose 应该合成为touchoose 就是这样两个单词&#xff0c;我们让一个指针指着第一个字符串…

计算机视觉yolov8模型应用-学习笔记

计算机视觉yolov8模型应用-学习笔记 YOLOv8是由Ultralytics公司在‌2023年1月10日‌发布的一款深度学习模型。它是YOLOv5的重大更新版本&#xff0c;支持图像分类、物体检测和实例分割任务。这一版本在发布前就受到了广泛关注&#xff0c;并在发布后迅速成为目标检测领域的热门…

【网络层协议】NAT技术内网穿透

IP地址数量限制 我们知道&#xff0c;IP地址&#xff08;IPv4&#xff09;是一个4字节32位的整数&#xff0c;那么一共只有2^32也就是接近43亿个IP地址&#xff0c;而TCP/IP协议栈规定&#xff0c;每台主机只能有一个IP地址&#xff0c;这就意味着&#xff0c;一共只有不到43亿…

深入理解 C++11 智能指针:独占、共享与弱引用的完美管理

文章目录 std::unique_ptr&#xff08;独占式智能指针&#xff09;std::shared_ptr&#xff08;共享式智能指针&#xff09;std::weak_ptr&#xff08;弱引用智能指针&#xff09;示例展示&#xff1a;智能指针的原理内存泄漏**什么是内存泄漏&#xff0c;内存泄漏的危害****如…

AI Agent开发大全第四课-提示语工程:从简单命令到AI对话的“魔法”公式

什么是提示语工程?一个让AI“听话”的秘密 如果你曾经尝试过用ChatGPT或者其他大语言模型完成任务,那么你一定遇到过这样的情况:明明你的问题是清晰的,但答案却离题万里;或者你认为自己提供的信息足够详尽,可结果还是不理想。问题出在哪?很多时候并不是因为AI不够聪明,…

大模型架构记录 【综述-文字版】

名词解释&#xff1a; Prompt &#xff1a;提示词&#xff0c;是一个非常关键的概念&#xff0c;它指的是用户输入的文本或指令&#xff0c;用于引导语言模型生成相应的回答或执行特定任务。 Prompt Engineering&#xff1a;&#xff08;提示工程&#xff09; 是一种通过设计…

【论文笔记】Transformer

Transformer 2017 年&#xff0c;谷歌团队提出 Transformer 结构&#xff0c;Transformer 首先应用在自然语言处理领域中的机器翻译任务上&#xff0c;Transformer 结构完全构建于注意力机制&#xff0c;完全丢弃递归和卷积的结构&#xff0c;这使得 Transformer 结构效率更高…

使用CSS3实现炫酷的3D翻转卡片效果

使用CSS3实现炫酷的3D翻转卡片效果 这里写目录标题 使用CSS3实现炫酷的3D翻转卡片效果项目介绍技术要点分析1. 3D空间设置2. 核心CSS属性3. 布局和定位 实现难点和解决方案1. 3D效果的流畅性2. 卡片内容布局3. 响应式设计 性能优化建议浏览器兼容性总结 项目介绍 在这个项目中…

SpringSecurity——基于角色权限控制和资源权限控制

目录 基于角色权限控制 1.1 自定义 UserDetailsService 1.2 加载用户角色 1.3. 给角色配置能访问的资源&#xff08;使用切面拦截&#xff0c;使用注解&#xff09; 总结 资源权限控制 2.2. 需要有一个用户&#xff1b;&#xff08;从数据库查询用户&#xff09; 2.2 基…

红宝书第十一讲:超易懂版「ES6类与继承」零基础教程:用现实例子+图解实现

红宝书第十一讲&#xff1a;超易懂版「ES6类与继承」零基础教程&#xff1a;用现实例子图解实现 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、ES6类的核心语法&#xff1a;把事物抽象成“模板” 想象你要设…

Python为Word文档添加书签并打包成exe

背景简述 由于一些工作场景&#xff0c;需要从多个Word文档中找到出现的关键词&#xff0c;并阅读关键词的上下文内容。文件可能几十个&#xff0c;手动操作太要命了。所以python尝试处理。 目录 背景简述思路第一步、功能实现结果验证 第二步、打包成exe2-1、基础准备2-2、打…

ROS导航工具包Navigation

一&#xff0c;安装 Navigation工具包包含在 navigation 元功能包中。你可以通过以下命令安装&#xff1a; sudo apt-get install ros-noetic-navigation 如果你使用的是其他ROS版本&#xff08;如Melodic&#xff09;&#xff0c;将 noetic 替换为对应的版本名称&#xff08…

资金管理策略思路

详细描述了完整交易策略的实现细节&#xff0c;主要包括输入参数、变量定义、趋势判断、入场与出场条件、止损与止盈设置等多个方面。 输入参数&#xff08;Input&#xff09;&#xff1a; EntryFrL (.6)&#xff1a;多头入场的前一日波动范围的倍数。 EntryFrS (.3)&#xff1…

工业软件的破局与重构:从技术依赖到自主创新的未来路径

工业软件作为现代工业的“神经与大脑”&#xff0c;不仅是制造业数字化转型的核心工具&#xff0c;更是国家工业竞争力的战略制高点。近年来&#xff0c;中国工业软件市场在政策驱动与技术迭代中迅猛发展&#xff0c;但核心技术受制于人的困境仍待突破。如何实现从“跟跑”到“…

常见中间件漏洞攻略-Tomcat篇

一、 CVE-2017-12615-Tomcat put方法任意文件写入漏洞 第一步&#xff1a;开启靶场 第二步&#xff1a;在首页抓取数据包&#xff0c;并发送到重放器 第三步&#xff1a;先上传尝试一个1.txt进行测试 第四步&#xff1a;上传后门程序 第五步&#xff1a;使用哥斯拉连接 二、后…

【Dive Into Stable Diffusion v3.5】2:Stable Diffusion v3.5原理介绍

【Dive Into Stable Diffusion v3.5】系列博文&#xff1a; 第1篇&#xff1a;开源项目正式发布——深入探索SDv3.5模型全参/LoRA/RLHF训练第2篇&#xff1a;Stable Diffusion v3.5原理介绍 目录 1 前言1.1 扩散模型的原理1.2 损失函数1.3 加噪流程1.4 推理流程1.5 negative pr…

英伟达黄仁勋2025GTC演讲深度解析:液冷GPU、AI工厂、机器人AI…...

目录 一、技术产品与架构升级&#xff1a;从芯片到算力工厂1. 新一代GPU与计算架构2. AI工厂与算力操作系统 二、AI技术演进&#xff1a;从生成式到物理AI1. AI发展的三大阶段2. 推理算力需求爆炸式增长 三、生态合作与行业落地1. CUDA生态与开源工具2. 跨行业合作案例 四、未来…

嵌入式项目:利用心知天气获取天气数据实验方案

【实验目的】 1、利用心知天气服务器获取指定位置天气数据 2、将天气数据解析并可视化显示到OLED屏幕 【实验原理】 【实验步骤】 官网注册

Ubuntu下用QEMU模拟运行OpenBMC

1、前言 在调试过程中&#xff0c;安装了很多依赖库&#xff0c;具体没有记录。关于kvm&#xff0c;也没理清具体有什么作用。本文仅记录&#xff0c;用QEMU成功的将OpenBMC跑起来的过程&#xff0c;做备忘&#xff0c;也供大家参考。 2、环境信息 VMware Workstation 15 Pro…