写在前面的话
相信大家对于这道题已经不陌生的了,但是往往会有人在这回忆过去:
“有人翱游世界,有人夜里看海,有人leetcode第一题做不出来……”
你一定不会,要不你怎么会来到这 ^-^
题目描述
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
解析
相信大家对于第一种暴力解法已经“融会贯通”了,因为……em是吧,就不解释了。
那么可能对于题目的要求:如何用小于 O(N^2) 时间复杂度的条件下完成?
一个大致的思路可能是用哈希?
可能对于搜索,更快的能想到是哈希,因为它的搜索是O(1)。那么如何用哈希是一个问题?
那么哈希要搜索什么?(what)
对,暴力解法中,困扰我们的问题是什么,就是寻找 target - nums[i] 这个值的过程,用了O(N)的复杂度。
所以,将要搜索的值放入哈希表,就解决了这个问题。
那么,怎么放(how)
a. 直接扫描存入。扫描每个值存入哈希表。(有问题吗?)
b. 遍历数组,对于当前元素 nums[i],在哈希表中寻找 target-nums[i] 是否存在。如果不存在,说明和nums[i] 匹配的值 target-nums[i] 并不存在于哈希表中。再将该值存入哈希表。
对于这两种方式。第一种显然是不可能的,因为假如我有两个相等的数存入,那么你用哪种哈希结构能存储?因为这里你还需要考虑到返回的结果是 “下标” ,所以你存入的方式一定是这样的一个键值对:
pair<nums[i] , i>
也就是,当前元素和元素的下标。那么如果有重复元素,就产生冲突了,因为这里的second存储的不是常规的计数值,而是当前元素的下标。
所以我们采用第二种实现方式,就可以理解为什么要这么遍历存储了。
当解决了存储问题之后,这个问题的思路就有了。
那么解决了target-nums[i] 这个值的查找情况的时候,这个题目也就解决了。
代码实现
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> mp;
for(int i=0;i<nums.size();i++)
{
auto it = mp.find(target-nums[i]);
if( it == mp.end())
mp[nums[i]]=i;
else
return {i,it->second};
}
return {};
}
};
Important
几个细节点,如果忽略细节,那么你看完了跟你将这个题目结果背了一遍,没有任何区别。
1.存储的是什么?为什么这么存储?能不能采用其他方式存储?
2.找对应值的时候,我们的思路是什么?
3.返回的值是什么?怎么返回呢?
相信如果你对于以上三个问题有了理解,那么下回你就不用一次又一次
“
又回到最初的起点,记忆中你超时的脸~
”
好的,如果你有不一样的思路请多多指教奥~