两数之和

力扣题目链接(opens new window)

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

思路

暴力法

两层for循环,一个一个加起来然后判断呗

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i = 0; i < nums.size(); i++){
for(int j = i + 1; j < nums.size(); j++){
if(nums[i] + nums[j] == target){
return {i, j};
}
}
}
//不满足条件返回空
return {};
}
};
哈希法

没错,这个题也可以用哈希法去解

只不过这里我们使用的哈希结构有所不同,先分析一下解题思路

题目要求我们找到数组中两个数,这两个数加起来要等于输入的target值

假设,现在遍历到数组的第一个数 A

C = target - A;

那么如果数组中存在 C 的话,我们就找到了两个符合条件的数{A, B},返回两者的下标即可

因此,我们需要有一个数据结构去存放已经遍历过的值和该值在数组中的下标

这是一个key-value的结构,对应到c++中可以通过map容器实现

C++中map,有三种类型:

映射 底层实现 是否有序 数值是否可以重复 能否更改数值 查询效率 增删效率
std::map 红黑树 key有序 key不可重复 key不可修改 O(log n) O(log n)
std::multimap 红黑树 key有序 key可重复 key不可修改 O(log n) O(log n)
std::unordered_map 哈希表 key无序 key不可重复 key不可修改 O(1) O(1)

std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。

因为本题并不需要key有序,所以使用unordered_map效率更高

那么key对应什么?value又对应什么呢?

我们想知道的是,某个值(当前遍历值与target作差之后的差值)是否被遍历过,即查找的对象是某个值,因此需要将遍历得到的数组元素值作为key,其下标作为value

流程

1、遍历数组,向unordered_map中查询当前遍历值对应的值是否被遍历过

2、如果查询到匹配值,返回该值对应的value,与当前遍历值的index组成一对结果

代码

主要障碍是对c++里面一些容器的操作不熟练(比如这里的map容器),这里直接粘的卡哥的代码

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//声明一个unordered_map
std::unordered_map <int,int> map;
for(int i = 0; i < nums.size(); i++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
// auto用于自动给迭代对象一个相应的数据类型
auto iter = map.find(target - nums[i]); //这里是定义了一个map的iterator吗?没见过这种写法
//end()指向的最后一个元素的后一个位置
//iter != map.end()是什么意思?其常被用于map容器遍历时的判断条件
//
if(iter != map.end()) { //找到了
/*
(*it).first会得到key,
(*it).second会得到value。
这等同于it->first和it->second
*/
//{匹配值下标, 当前遍历值的下标}
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};

后续需要对c++容器的使用做强化训练(专题:c++刷题常用容器简介,TBD)

关于iter != map.end()

这里需要从它的上一行代码开始说起

摘自《C++ Primer Plus第6版》:

C++11新增了一个工具,让编译器能够根据初始值的类型推断变量的类型。为此,它重新定义了auto的含义。auto是一个C语言关键字,但很少使用,有关其以前的含义,请参阅第9章。在初始化声明中,如果使用关键字auto,而不指定变量的类型,编译器将把变量的类型设置成与初始值相同:

那么auto iter = map.find(target - nums[i]);的含义是:

定义一个 迭代器iter 用于在 map 中寻找 target - nums[i]

如果 map.find(target - nums[i]) 等于 map.end() ,那么键就没有找到。

否则,find会返回一个指向找到的元素的迭代器。

上述题解中的代码可写为:

std::unordered_map <int,int> map;
unordered_map <int,int> ::iterator it = map.find(target - nums[i]); if (i != m.end()) { /* 找到了, 此时i->first就是匹配值下标(key), i->second是当前遍历值的下标(value) */}
else { /* 没找到f */ }

参考:https://stackoverflow.com/a/1939962/15272780

二刷

简化了之前的代码

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hashmap;
for(int i = 0; i < nums.size(); ++i){
if(hashmap.find(target - nums[i]) != hashmap.end()){
return {hashmap[target - nums[i]], i};
}
hashmap.insert(pair<int, int>(nums[i], i));
}
return {};
}
};

有一个关键点是:我们是使用遍历值与target作差,差值作为key,下标作为value

所以可以通过差值查询“差值是否在map中”

【LeetCode哈希表#4】梦开始的地方:两数之和(map),以及关于容器map的一些代码技巧的更多相关文章

  1. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  2. [LeetCode] 653. Two Sum IV - Input is a BST 两数之和之四 - 输入是二叉搜索树

    Given a Binary Search Tree and a target number, return true if there exist two elements in the BST s ...

  3. leetcode 刷题(数组篇)1题 两数之和(哈希表)

    题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元 ...

  4. 【leetcode】170. Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:  add and find. add  ...

  5. [LeetCode] 167. Two Sum II - Input array is sorted 两数和 II - 输入是有序的数组

    Given an array of integers that is already sorted in ascending order, find two numbers such that the ...

  6. [LeetCode] 170. Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:add and find. add - ...

  7. C++ undered_map哈希表用法——leetcode两数之和

    undered_map 头文件:#include<undered_map> 创建表undered_map<key,value> Map_name; 插入元素 a[key]=va ...

  8. 【数据结构】Hash表简介及leetcode两数之和python实现

    文章目录 Hash表简介 基本思想 建立步骤 问题 Hash表实现 Hash函数构造 冲突处理方法 leetcode两数之和python实现 题目描述 基于Hash思想的实现 Hash表简介 基本思想 ...

  9. LeetCode:乘法表中的第K小的数【668】

    LeetCode:乘法表中的第K小的数[668] 题目描述 几乎每一个人都用 乘法表.但是你能在乘法表中快速找到第k小的数字吗? 给定高度m .宽度n 的一张 m * n的乘法表,以及正整数k,你需要 ...

  10. 167. 两数之和 II - 输入有序数组 + 哈希表 + 双指针

    167. 两数之和 II - 输入有序数组 LeetCode_167 题目描述 方法一:暴力法(使用哈希表) class Solution { public int[] twoSum(int[] nu ...

随机推荐

  1. Redis scan等命令的学习与研究

    Redis scan等命令的学习与研究 摘要 背景跟前几天说的一个问题类似. 为了验证自己的设想, 所以晚上继续写脚本进行了一轮次的验证. 不过上次讨论时,打击好像都没听懂我说的 所以这次准备从基础开 ...

  2. [转帖]看6大国产CPU加速替代,谁才是“王者”选手?

    https://baijiahao.baidu.com/s?id=1761150458273739276&wfr=spider&for=pc 2023-03-23 17:33湖北匠心计 ...

  3. Linux 一行命令 仅显示某一个网卡的ip地址

    最简答的方法 1. 先使用 ifconfig 查看网卡的设备名 2. 然后输入命令 ifconfig ens192 |grep 'inet ' |cut -d " " -f 10命 ...

  4. c++ container容器(string,vector,map,queue,stack等等)

    STL和c++标准库 标准模板库STL部分包含在C++标准库中的软件库. c++标准库:即以std::开头,但是部分编译器厂商也会把STL的内容放在std:: namespace里面 由于一个常见的误 ...

  5. 强化学习基础篇【1】:基础知识点、马尔科夫决策过程、蒙特卡洛策略梯度定理、REINFORCE 算法

    强化学习基础篇[1]:基础知识点.马尔科夫决策过程.蒙特卡洛策略梯度定理.REINFORCE 算法 1.强化学习基础知识点 智能体(agent):智能体是强化学习算法的主体,它能够根据经验做出主观判断 ...

  6. C/C++ 反汇编:数据类型与常量

    反汇编即把目标二进制机器码转为汇编代码的过程,该技术常用于软件破解.外挂技术.病毒分析.逆向工程.软件汉化等领域,学习和理解反汇编对软件调试.系统漏洞挖掘.内核原理及理解高级语言代码都有相当大的帮助, ...

  7. layui下拉框可手动输入

    先看效果 layui版本:layui@2.8.17 HTML代码: <div class="layui-form-item"> <label class=&quo ...

  8. 英特尔发布酷睿Ultra移动处理器:Intel 4制程工艺、AI性能飙升

    英特尔今日发布了第一代酷睿Ultra移动处理器,是首款基于Intel 4制程工艺打造的处理器. 据了解,英特尔酷睿Ultra采用了英特尔首个用于客户端的片上AI加速器"神经网络处理单元(NP ...

  9. P9989 [Ynoi Easy Round 2023] TEST_69 题解

    题目链接: [Ynoi Easy Round 2023] TEST_69 首先GCD有比较良好的一些性质.我们观察到一次 \(GCD(a_i,x)\) 操作,会有以下两种变化. 如果 \(x \bmo ...

  10. 《ASP.NET Core 微服务实战》-- 读书笔记(第12章)

    第 12 章 设计汇总 微服务开发并不是要学习 C#.Java 或者 Go 编程--而是要学习如何开发应用以适应并充分利用弹性伸缩环境的优势,它们对托管环境没有偏好,并能瞬间启停 换句话说,我们要学习 ...