【题解】Leetcode #1. 两数之和
题意简述
给定整数数组nums
(以下简写为\(a\))和目标值target
(以下简写为\(t\)),求一组\((i,j)\),其中\(0\leq i,j<n\),使得\(a_i+a_j=t\)。
思路
我们来考虑暴力枚举。根据题意明显可以两层循环分别枚举\(i\)和\(j\),当找到符合题意的一组\((i,j)\)时,直接输出。时间复杂度\(O(n^2)\),用leetcode
水爆了的数据显然能过。
【代码】
class Solution
{
public:
#define n nums.size()
vector<int> twoSum(vector<int>& nums, int target)
{
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (nums[i] + nums[j] == target)
return {i, j};
return {};
}
};
运行数据:71ms/12.67MB
如何考虑更优的时间复杂度?我们注意到如果我们能够用\(O(1)\)的时间来处理和查询在先前的遍历中找到的数据信息反向映射,这样可以将时间复杂度优化到\(O(n)\),但是额外代价就是消耗了复杂度为\(O(n)\)的空间。我们的正向映射是题目中已经给出的,反向映射就不得不提到我们今天算法的主角:哈希表。
这样我们创建一个哈希表,对于每一个\(x\),我们首先查询哈希表中是否存在\(t - x\),然后将\(x\)插入到哈希表中,即可保证不会让\(x\)和自己匹配。
【代码】
class Solution
{
public:
#define n nums.size()
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> mp;
for (int i = 0; i < n; i++)
{
if (mp.find(target - nums[i]) != mp.end())
return {mp[target - nums[i]], i};
mp[nums[i]] = i;
}
return {};
}
};
运行数据:14ms/14.04MB