138 lines
4.6 KiB
Markdown
138 lines
4.6 KiB
Markdown
# 题目地址
|
||
https://leetcode-cn.com/problems/two-sum/
|
||
|
||
> 只用数组和set还是不够的!
|
||
|
||
# 第1题. 两数之和
|
||
|
||
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
|
||
|
||
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
|
||
|
||
**示例:**
|
||
|
||
给定 nums = [2, 7, 11, 15], target = 9
|
||
|
||
因为 nums[0] + nums[1] = 2 + 7 = 9
|
||
|
||
所以返回 [0, 1]
|
||
|
||
|
||
# 思路
|
||
|
||
很明显暴力的解法是两层for循环查找,时间复杂度是O(n^2)。
|
||
|
||
建议大家做这道题目之前,先做一下这两道
|
||
* [242. 有效的字母异位词](https://mp.weixin.qq.com/s/vM6OszkM6L1Mx2Ralm9Dig)
|
||
* [349. 两个数组的交集](https://mp.weixin.qq.com/s/N9iqAchXreSVW7zXUS4BVA)
|
||
|
||
[242. 有效的字母异位词](https://mp.weixin.qq.com/s/vM6OszkM6L1Mx2Ralm9Dig) 这道题目是用数组作为哈希表来解决哈希问题,[349. 两个数组的交集](https://mp.weixin.qq.com/s/N9iqAchXreSVW7zXUS4BVA)这道题目是通过set作为哈希表来解决哈希问题。
|
||
|
||
本题呢,则要使用map,那么来看一下使用数组和set来做哈希法的局限。
|
||
|
||
* 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
|
||
* set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下表位置,因为要返回x 和 y的下表。所以set 也不能用。
|
||
|
||
此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下表。
|
||
|
||
C++中map,有三种类型:
|
||
|
||
|映射 |底层实现 | 是否有序 |数值是否可以重复 | 能否更改数值|查询效率 |增删效率|
|
||
|---|---| --- |---| --- | --- | ---|
|
||
|std::map |红黑树 |key有序 |key不可重复 |key不可修改 | O(logn)|O(logn) |
|
||
|std::multimap | 红黑树|key有序 | key可重复 | key不可修改|O(logn) |O(logn) |
|
||
|std::unordered_map |哈希表 | key无序 |key不可重复 |key不可修改 |O(1) | O(1)|
|
||
|
||
std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。
|
||
|
||
同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。 更多哈希表的理论知识请看[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/g8N6WmoQmsCUw3_BaWxHZA)。
|
||
|
||
**这道题目中并不需要key有序,选择std::unordered_map 效率更高!**
|
||
|
||
解题思路动画如下:
|
||
|
||
<video src='../video/1.两数之和.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
|
||
|
||
# C++代码
|
||
|
||
```
|
||
class Solution {
|
||
public:
|
||
vector<int> twoSum(vector<int>& nums, int target) {
|
||
std::unordered_map <int,int> map;
|
||
for(int i = 0; i < nums.size(); i++) {
|
||
auto iter = map.find(target - nums[i]);
|
||
if(iter != map.end()) {
|
||
return {iter->second, i};
|
||
}
|
||
map.insert(pair<int, int>(nums[i], i));
|
||
}
|
||
return {};
|
||
}
|
||
};
|
||
```
|
||
|
||
## 一般解法
|
||
|
||
代码:
|
||
|
||
```C++
|
||
```
|
||
|
||
## 优化解法
|
||
|
||
```C++
|
||
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 {};
|
||
}
|
||
};
|
||
|
||
```
|
||
|
||
```
|
||
class Solution {
|
||
public:
|
||
vector<int> twoSum(vector<int>& nums, int target) {
|
||
std::map <int,int> map;
|
||
for(int i = 0; i < nums.size(); i++) {
|
||
auto iter = map.find(target - nums[i]);
|
||
if(iter != map.end()) {
|
||
return {iter->second,i};
|
||
}
|
||
map.insert({nums, i});
|
||
}
|
||
return {};
|
||
}
|
||
};
|
||
```
|
||
|
||
```
|
||
class Solution {
|
||
public:
|
||
vector<int> twoSum(vector<int>& nums, int target) {
|
||
std::unordered_map <int,int> map;
|
||
for(int i = 0; i < nums.size(); i++) {
|
||
auto iter = map.find(target - nums[i]);
|
||
if(iter != map.end()) {
|
||
return {iter->second, i};
|
||
break;
|
||
}
|
||
map.emplace(nums[i], i);
|
||
}
|
||
return {};
|
||
}
|
||
};
|
||
```
|
||
|
||
> 更过算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||
|