当前位置: 代码迷 >> 综合 >> LeetCode 1 两数之和(哈希表、unordered_map)
  详细解决方案

LeetCode 1 两数之和(哈希表、unordered_map)

热度:94   发布时间:2023-12-18 21:10:51.0

题目要求:

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

 

 

 

C++代码(8ms):

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

 

 

结果:

 

 

 

穷举法解析:

当然最简单直接和暴力的方法就是迭代2次for循环,

代码理解比较简单,就是对于nums数组里的每个元素,拿它跟后面的元素一一做加法,如果他们两者之和刚好等于target的值,那么就把这两个位置(i,j)push_back进result里面,最后再返回result即可。

但是不可避免地,我们做了很多重复计算,时间复杂度是很高的。

代码如下(192ms):

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> result;for(int i = 0; i < nums.size();i++){for(int j = i+1;j< nums.size();j++){if(nums[i]+nums[j] == target){result.push_back(i);result.push_back(j);break;}}}return result;}
};

 

 

 

较优解法解析:

而我们的8ms的代码用到了unordered_map,即无序映射,它是关联容器,用于存储由键值和映射值组合而成的元素,并允许基于键快速检索各个元素,很类似python里面的list。

不懂的朋友可以看这篇博文:unordered_map的用法

 

因此首先我们创建一个unordered_map的对象map,其key和value类型均是int型的

unordered_map<int, int> map;

然后我们对于nums数组里的每个元素遍历,(注意,之前穷举法是,不管找没找到,全部元素都遍历完,而我这边找完就截止查找,所以时间复杂度就低了,因为没必要做无谓的多余的查找)

for (int i = 0; i < n; i++) {
   

这里建立的unordered_map,其key就是实际的值,也就是nums[i]对应的值,比如题目中的2、7、11、15,而value就是2、7、11、15所在的位置,如0、1、2、3(目的就是通过求出target-nums[i],是否在我们之前保存的unordered_map里面)

之后通过map.find查找,找到了就返回一个iterator值,并保存在p变量,找不到则返回map.end()

auto p = map.find(target-nums[i]);

如果找到了,也就是

 

if (p!=map.end()) {
   

那么就返回2个数的位置,第一个数就是p这个iterator的second,也就是它的value,因为value存的就是位置,然后第二个数就直接返回i即可

 return {p->second, i};

如果找不到,那么就把当前这个数和他的位置存入unordered_map中,比如我的第一个元素是2,最开始unordered_map里面当然找不到它对应的target-nums[i]也就是9-2=7,所以就把key-2,value-0存入unordered_map里面

那么当我下一个元素是7时,计算target-nums[i]也就是9-7=2,在unordered_map里面去找,找到key-2,所以就返回了p->second也就是p的value,即key-2的value,也就是0,以及当前的i也就是1

map[nums[i]]=i;