1. 两数之和(力扣LeetCode)

文章目录

  • 1. 两数之和
    • 题目描述
    • 哈希表:map
    • 二分查找
    • 暴力:双重for循环

1. 两数之和

题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

哈希表:map

使用map需要明确两点:

  • map用来做什么
  • map中key和value分别表示什么

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

接下来是map中key和value分别表示什么。

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

过程如下:
在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {// 创建一个哈希表来存储数组元素和它们的索引unordered_map<int, int> map;//map.find() 返回的是一个迭代器(std::unordered_map<int, int>::iterator),它存储的元素是 std::pair<const Key, T> 类型的对象// 遍历数组中的每个元素,索引为ifor (int i = 0; i < nums.size(); i++) {//枚举a:这里其实是将a+b=target转换为target-a=b,然后在数组中查找b是否存在// 尝试在哈希表中找到与当前元素相加等于target的元素auto b = map.find(target - nums[i]);// 如果找到了这样的元素if (b != map.end()) {// 返回一个包含两个索引的数组,i是当前元素的索引,// b->second是之前存储在哈希表中的配对元素的索引return { i, b->second };}// 如果没有找到配对元素,将当前元素的值和索引存入哈希表map.insert(pair<int, int>(nums[i], i));//相当于map[nums[i]]=i;}// 如果没有找到任何满足条件的元素对,返回一个空数组return {};}
};
  • auto:auto 关键字用于自动类型推断。它指示编译器自动推断变量的类型,根据变量的初始化表达式来确定其类型。

  • map.find():

    • 如果键 target - nums[i] 存在于 map 中,find 函数返回一个迭代器,指向 unordered_map 中含有该键的键值对。
    • 如果键不存在,find 函数返回一个特殊的迭代器 map.end(),这个迭代器指向 unordered_map 结尾的位置,这表明搜索失败。
  • pair:在C++中,pair 是一个结构,定义在 头文件中,它可以将两个值合并成一个单元。这两个值可以是不同的数据类型。pair 最常见的用途是在关联容器中,如 std::map 或 std::unordered_map,其中每个元素都是一个键值对。

    • pair 的构造函数接受两个参数,分别对应 pair 的两个成员:first 和 second,其中:

      • first 成员变量将存储键(nums[i]),
      • second 成员变量将存储与键关联的值(i)。

二分查找

这道题并不推荐二分,因为需要考虑的东西太多:

  • 使用二分算法查找需要对数组排序,一旦排序就会破坏原来的下标,我这里用一个新的num2复制 nums 数组,因为后面会对 nums 进行排序,这样做是为了保留原始元素的索引。
  • 因为下标的变动还需要使用num2去寻找原来的下标
  • 寻找原来下标中也有坑,如果两个数相同,就需要从下一个数开始寻找,不然会得到相同的下标:如下
// 如果两个找到的数字相同,需要找到第二个相同数字的索引if (nums[i] == nums[z]) v = v + 1;else v = 0;

总代码如下,比较复杂,所以并不推荐二分,因为一开始感觉像我做过的A-B 数对这道题,觉得可以用二分查找做出来,仅此记录而已

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {// 复制原数组nums到num2,用于在排序后找回原始索引vector<int> num2(nums.begin(), nums.end());// 对nums进行快速排序quick_sort(nums, 0, nums.size() - 1);vector<int> num;// 遍历排序后的数组,寻找是否存在两个数的和等于targetfor (int i = 0; i < nums.size(); i++) {// 计算与当前数字nums[i]相配对的数字int b = target - nums[i];// 使用二分查找法在nums中查找bint z = find(b, nums);cout << z << endl;// 如果找到了b,并且它的索引不是i(确保不是同一个元素)if (z != -1 && z != i) {// 查找nums[i]在原数组num2中的索引int v = find_xb(0, num2, nums[i]);num.push_back(v);// 如果两个找到的数字相同,需要找到第二个相同数字的索引if (nums[i] == nums[z]) v = v + 1;else v = 0;// 查找nums[z]在原数组num2中的索引num.push_back(find_xb(v, num2, nums[z]));// 返回结果数组,包含两个找到的索引return num;}// 如果没有找到,则继续循环else continue;}// 如果没有找到任何匹配的元素对,返回一个空数组return vector<int>();}// 快速排序算法的实现
private:void quick_sort(vector<int>& nums, int l, int r) {// 如果子数组长度为0或1,则返回if (l >= r) return;// 初始化指针和基准值int i = l - 1, j = r + 1, x = nums[(l + r) >> 1];while (i < j) {// 移动左指针直到找到一个大于等于x的元素do i++; while (nums[i] < x);// 移动右指针直到找到一个小于等于x的元素do j--; while (nums[j] > x);// 如果i<j,交换两个元素if (i < j) swap(nums[i], nums[j]);}// 递归地对左右子数组继续排序quick_sort(nums, l, j);quick_sort(nums, j + 1, r);}// 二分查找算法的实现int find(int n, vector<int>& nums) {int l = 0, r = nums.size() - 1;while (l < r) {int mid = (l + r) >> 1;if (nums[mid] >= n) r = mid;else l = mid + 1;}// 检查是否找到目标nif (nums[l] == n) return l;return -1;}// 在原数组中查找给定的数字并返回其索引int find_xb(int v, vector<int>& num, int n) {// 从给定的起始索引v开始查找for (int i = v; i < num.size(); i++) {// 如果找到了,就返回索引if (num[i] == n)return i;}// 这个循环理论上不会运行到结尾,因为前面的逻辑保证了n在num中// 这里没有返回值,实际上应该有一个返回值来保证函数完整性return -1; // 增加默认返回值}
};

暴力:双重for循环

该代码的工作原理是:

  • 遍历数组 nums 中的每个元素,索引为 i。
  • 对于每个 i,再次遍历其之后的每个元素,索引为 j。
  • 对于每对 (i, j),检查 nums[i] 和 nums[j] 的和是否等于 target。
  • 如果找到这样的一对 (i, j),则将它们的索引作为答案返回。
  • 如果遍历完所有的元素对也没有找到满足条件的对,那么返回一个空的数组。

时间复杂度和空间复杂度分析:

  • 时间复杂度:O(n^2),因为有两个嵌套循环,每个循环都可能遍历整个数组 nums。
  • 空间复杂度:O(1),因为除了存储结果所需的空间之外,不需要额外的存储空间。
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {// 定义一个向量来存放结果vector<int> num;// 外层循环遍历数组中的每一个元素,除了最后一个for (int i = 0; i < nums.size() - 1; i++) {// 内层循环从当前元素的下一个开始遍历for (int j = i + 1; j < nums.size(); j++) {// 检查当前对的元素和是否等于目标值if (nums[i] + nums[j] == target) {// 如果等于目标值,则将两个数字的索引添加到结果向量中num.push_back(i);num.push_back(j);// 返回结果,不需要继续查找return num;}}}// 如果没有找到符合条件的两个数,返回空向量return vector<int>();}
};

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

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

相关文章

24. 两两交换链表中的节点(力扣LeetCode)

文章目录 24. 两两交换链表中的节点题目描述解题思路只使用一个临时节点使用两个临时节点 24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff0…

angular2 开发遇到的问题

1&#xff1a;插件使用&#xff0c;要一同引入 不然报错 “ \ Changes detected. Rebuilding...X [ERROR] NG8001: sf-dashboard-overview is not a known element:”

微信扫码登录流程

微信官方文档使用 搜索“微信开放平台”点击导航栏的“资源中心”点击“网站应用”下的“微信登录功能”地址微信扫码登录是基于OAuth2的&#xff0c;所以需要第三方应用&#xff08;就是实现微信扫码登录的应用&#xff09;成为微信的客户端&#xff0c;获取AppId和AppSecret…

Linux 进程管理

一、简述 当运行一个程序的时候&#xff0c;那么运行的这个程序就叫做进程。程序&#xff0c;是一个静态的概念统称为软件&#xff0c;相当于一个被编译好可执行的二进制文件&#xff0c;同时程序可以长期存在系统中&#xff1b;进程&#xff0c;是一个动态的概念&#xff0c;…

RHCE练习3

1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教学资料www.openlab.com/mo…

Unix环境高级编程-学习-04-匿名管道PIPE

目录 一、环境 二、介绍 三、C标准函数介绍 1、pipe 2、popen 3、pclose 4、注意 四、宏 五、常见的管道用法 1、一对一&#xff08;父进程读子进程写一条管道&#xff09; 2、一对一&#xff08;父进程写子进程读一条管道&#xff09; 3、一对多&#xff08;父进程…

leetcode—跳跃游戏—贪心算法

1 跳跃游戏1 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&a…

vue-computed 计算属性

一、computed 计算属性 在Vue应用中&#xff0c;在模板中双向绑定一些数据或者表达式&#xff0c;但是表达式如果过长&#xff0c;或者逻辑更为复杂 时&#xff0c;就会变得臃肿甚至难以维护和阅读&#xff0c;例如&#xff1a; <div>写在双括号中的表达式太长了,不利于阅…

Linux 入门基础知识(一)—— Linux的基本使用

Linux 入门基础知识 一、Linux的基本使用和配置1.1、终端1.2、消耗内存1.3、运行级别1.6、登录前欢迎语1.5、登录后欢迎语1.6、shell1.7、ps aux1.8、设置主机名1.9、whoami和who am i1.10、命令提示符 二、Linux执行命令的过程详解和命令类型2.1、命令执行2.2、hash缓存表2.3、…

张维迎《博弈与社会》纳什均衡与囚徒困境博弈(2)囚徒困境博弈

囚徒困境大家应该都比较熟悉了&#xff0c;我觉得这篇的意义大概在与&#xff0c;经济学术语的运用&#xff1f; 囚徒困境&#xff1a;个人理性与集体理性的矛盾 假定有两个犯罪嫌疑人共同作案。警察抓住他们以后&#xff0c;分开拘押&#xff0c;并告诉他们&#xff1a;可以选…

Chiplet,汽车“芯”风向

异构集成、高速互联、算力灵活可扩展正在成为新一轮汽车芯片竞争的焦点。尤其是随着以ChatGPT为代表的大数据、大模型产品在车端的落地&#xff0c;对于芯片的要求还在持续提升。 本周&#xff0c;12家日本汽车制造商&#xff08;包括丰田、日产、本田等&#xff09;、零部件制…

设计与实现基于Java+MySQL的考勤发布-签到系统

课题背景 随着现代经济的迅速发展&#xff0c;电子考勤签到服务已经渗透到人们生活的方方面面&#xff0c;成为不可或缺的一项服务。在这个背景下&#xff0c;线上签到作为考勤签到的一种创新形式&#xff0c;为用户提供了便捷的操作方式&#xff0c;使得任务签到、个人签到记…

代码随想录算法训练营第35天 | 860.柠檬水找零 406.根据身高重建队列 452.用最少数量的箭引爆气球

柠檬水找零 局部最优&#xff1a;收到20元时优先找零10元5元&#xff0c;不够再找零3个5元&#xff0c;因为5元可以找零20和10&#xff0c;更有用。全局最优&#xff1a;完成所有的找零。 class Solution { public:bool lemonadeChange(vector<int>& bills) {int fi…

c++的发展史、缺省参数、命名空间你了解吗?

1.c的发展历史概述 1.1.什么是c C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的 程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20世纪80年代&#xff0c; 计算机…

TypeScript实战系列之强力爆破泛型的困扰

目录 介绍开始如何理解泛型语法泛型约束泛型默认值练习后续 介绍 泛型在typescript 中使用频率相当高&#xff0c;也给了初学者相当大的阻碍。希望这一篇文章&#xff0c;能帮助你们爆破它。 开始 下面通过模拟实现一个简易版本的axios来引入泛型的使用 // axios.ts type M…

如何在centos7上配置为桥接模式

一、打开虚拟机的设置页面&#xff0c;设置虚拟机桥接模式如图&#xff1a;选择桥接模式&#xff08;复制物理网络连接可选&#xff09; 二、net0对应桥接模式的配置&#xff0c;如下方式选择 三、 在 CentOS 7 中&#xff0c;通过编辑网络配置文件来配置网络参数。找到 /etc…

(九)springboot实战——springboot3下的webflux项目参数验证及其全局参数验证异常处理

前言 在上一节内容中&#xff0c;我们介绍了如何在webflux项目中自定义实现一个全局的异常处理器ErrorWebExceptionHandler&#xff0c;正常情况下其可以处理我们系统的运行时异常&#xff0c;但是无法处理参数验证的异常WebExchangeBindException&#xff0c;所以这里提供另外…

算法随想录第四十八天打卡| 198.打家劫舍 , 213.打家劫舍II , 337.打家劫舍III

详细布置 今天就是打家劫舍的一天&#xff0c;这个系列不算难&#xff0c;大家可以一口气拿下。 198.打家劫舍 视频讲解&#xff1a;动态规划&#xff0c;偷不偷这个房间呢&#xff1f;| LeetCode&#xff1a;198.打家劫舍_哔哩哔哩_bilibili 代码随想录 class Solution(…

STM32 E18-D80NK红外避障传感器

E18-D80NK-N是一款红外光电传感器&#xff0c;它同时具备发射和接收功能。通过对发射光进行调制后发出&#xff0c;并通过接收头对反射光进行解调输出。 E18-D80NK-N采用了透镜来增强传感器的性能&#xff0c;使其能够检测更远的距离。根据红外光的特性&#xff0c;不同颜色的…

拒掉了一个双 985 的面试者

下班路上&#xff0c;和一个大佬聊天&#xff0c;他说今天面试&#xff0c;拒掉了一个双 985 的候选人。 候选人背景很好&#xff0c;本科和硕士都是 985 院校毕业&#xff0c;并且是除了清北浙之外&#xff0c;排名非常靠前的 985院校。 本硕专业都是计算机专业&#xff0c;…