力扣1. 两数之和
题目来源(力扣):
https://leetcode.cn/problems/two-sum/description/
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值target的那 两个 整数,并返回它们的数组下标。
保证只会出现一个答案
基本思路:
就是已知a+b=c,求数组中是否存在a和b使得式子成立。
先对问题简化:
如果假设数组nums[]中各个数字都是不同的,那么直接对数组构建哈希表m(这里用std::unordered_map),m存储的是每个数的下标(从1开始而非从0开始,便于判断真假)
之后再扫一遍数组nums[],对于nums[i],如果val=c-nums[i]在哈希表中,则返回[i,m[val]-1] (m[val]-1,因为vector从下标0开始)
简化代码(无法通过所有样例)
class Solution
{
public:
vector<int> twoSum(vector<int> &nums, int target)
{
unordered_map<int, int> m;
vector<int> ans;
for (int i = 0; i < nums.size(); i++) //直接对数组构建哈希表m
{
m[nums[i]] = i + 1; //m存储的是每个数的下标 ,从1开始
}
for (int i = 0; i < nums.size(); i++)
{
int val = target - nums[i]; //nums[i]在数组内
if (m[val]) //如果val也在数组内,则找到答案
{
ans.push_back(m[val] - 1);
ans.push_back(i);
break;
}
}
return ans;
}
};
错误原因
首先,原数组中,同一个数可以出现多次,例如[3,3,4],则返回答案应该为[0,1](或者[1,0]),而非[0,0]或[1,1]
其次,当数组中出现某数为目标c的一半时,不能重复取它,即题目中要求的“请你在该数组中找出和为目标值target的那 两个 整数”,
例如[1,3,7,9,5],而目标值为14,则返回答案应该为[3,4](或者[4,3]),而非[2,2]
一个解决方法就是,边建表边判断
具体而言,对于当前要进入到哈希表m中的nums[i],考虑val=target-nums[i],如果val已经哈希表中,则返回[i,m[val]-1]
否则,将nums[i]加入到哈希表m中,即m[nums[i]]=i+1;
会发现和简化的思路完全一致(甚至代码也高度相似),只是将“先建表后判断”改为了“边建表边判断”,就能避免出现各种问题了~(想想为什么)
完整代码如下
class Solution
{
public:
vector<int> twoSum(vector<int> &nums, int target)
{
unordered_map<int, int> m;
vector<int> ans;
for (int i = 0; i < nums.size(); i++)
{ //nums[i]在数组内
int val = target - nums[i]; //如果val也在数组内
if (m[val]) //则找打答案
{
ans.push_back(m[val] - 1);
ans.push_back(i);
break;
}
m[nums[i]] = i + 1; //将nums[i]加入到m中
}
return ans;
}
};
《代码随想录》写法:
写得更加简洁,但是思路完全一致
利用find,从而无需对下标进行+1和-1操作
class Solution
{
public:
vector<int> twoSum(vector<int> &nums, int target)
{
unordered_map<int, int> m;
for (int i = 0; i < nums.size(); i++)
{
auto iter = m.find(target - nums[i]);
if (iter != m.end())
{
return {iter->second, i}; // 等价于 return {m[nums[target-nums[i]]], i}
}
m.insert(pair<int, int>(nums[i], i)); // 等价于 m[nums[i]]=i;
}
return {};
}
};
时间复杂度
这里使用std::unordered_map ,时间复杂度为O(n),其中n为数组大小
如果采用普通的std::map ,则时间复杂度为O(nlogn),n为数组大小
浙公网安备 33010602011771号