两数之和

力扣题目链接(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. 我们开源了一个 Ant Design 的单元测试工具库

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:佳岚 欢迎大家点一个小小的 Star ant-design ...

  2. VOP 消息仓库演进之路|如何设计一个亿级企业消息平台

    作者:京东零售 李孟冬 VOP作为京东企业业务对外的API对接采购供应链解决方案平台,一直致力于从企业采购数字化领域出发,发挥京东数智化供应链能力,通过产业链上下游耦合与链接,有效助力企业客户的成本优 ...

  3. 去除 i 标签的倾斜样式;如何引入本地的阿里字体图标

    去除 i 标签的倾斜样式 i{ font-style:normal; } 如何引入本地的阿里字体图标 将代码下载下来 当然你将下载下载来的资源有用的放在静态资源中 然后在 main.js 引入: ma ...

  4. 小白学k8s(6)使用kubespray部署k8s

    kubespray部署k8s 准备 需要关闭防火墙 配置hosts 处理镜像 配置文件 运行 通过对应的镜像 运行代码 查看结果 出现的问题 墙 错误的配置 kubespray部署k8s 准备 kub ...

  5. 分布式ID介绍&实现方案总结

    分布式 ID 介绍 什么是 ID? 日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单 ID 对应且仅对应一个订单. ...

  6. 2.11 PE结构:添加新的节区

    在可执行PE文件中,节(section)是文件的组成部分之一,用于存储特定类型的数据.每个节都具有特定的作用和属性,通常来说一个正常的程序在被编译器创建后会生成一些固定的节,通过将数据组织在不同的节中 ...

  7. 重写JSON.stringify与JSON.parse使其支持解析function类型

    const JSONStringify = (option) => { return JSON.stringify(option, (key, val) => { // 处理函数丢失问题 ...

  8. 协程(Python)

    一.gevent #__author__:Kelvin #date:2020/5/13 13:34 from gevent import monkey monkey.patch_all() impor ...

  9. powerDesigner 逆向工程 mysql 生成 PDM

     1. 信息补充说明 powerDesigner  16.5 mysql 5.6 主要内容:使用powerDesigner的逆向工程,将mysql中的数据库转换成PDM文件 所需资源: powerDe ...

  10. 【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程

    1.作品图 2.准备工作 目前网上能搜到的stable-diffusion-webui的安装教程都是Window和Mac M1芯片的,而对于因特尔芯片的文章少之又少,这就导致我们还在用老Intel 芯 ...