解法一:暴力解法
暴力解法的思路较为直接,在输入数组中分别对两个下标进行遍历,若满足题目要求,直接返回结果(题目中明确说明假设答案唯一)。
注意:
- 第一层循环应从0到n-2位置(n为数组长度),即不需要遍历到数组最后一个元素;
- 第二层循环应将第一层循环变量作为起点,遍历至数组最后一个元素。
- 下标从1开始,因此在保存结果时,要注意加1。
代码如下:
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
int n = numbers.size();
vector<int> res;
// 数组为空
if (!n)
return res;
// 两层循环 暴力求解
for (int i = 0; i < n - 1; i ++) { // 从遍历至n-2位置
for (int j = i + 1; j < n; j ++) { // 从i遍历至n-1位置
if (numbers[i] + numbers[j] == target) {
// 下标从1开始
res.push_back(i + 1);
res.push_back(j + 1);
return res;
}
}
}
return res;
}
}; 该方法采用两层循环遍历原数组,因此时间复杂度为平方级别,即O(N^2);该方法未定义额外空间(除保存结果所需要的数组外),因此空间复杂度为O(1)。
解法二:哈希表
上述方法的时间复杂度可以进一步优化至O(N)。
哈希表的思想为「以空间换时间」,这是由于哈希表保存了键值对,其「查找」复杂度为O(1)。
对于本题,具体解题思路为(如图所示):
定义哈希表hashmap,其存放的键值对为<取值,下标>。
从开始处遍历数组,对于第i个位置,在哈希表中寻找target-nums[i]是否存在,若存在,将两个下标放入数组中返回;若不存在,将其添加至表中,继续遍历。
注:在将结果保存至数组中时,无需判断二者下标大小:当所遍历到的位置符合题目要求时,说明哈希表中已经存在待查找的另一元素,因此「已存在于表中的元素的下标」一定小于「当前位置元素的下标」。
代码实现如下:
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
int n = numbers.size();
vector <int> res;
if (!n)
return res;
// 定义哈希表,unordered_map是用哈希表实现的,复杂度为O(1),而map是用红黑树实现的
unordered_map<int, int> hashmap;
for (int i = 0; i < n; i ++) {
if (hashmap.find(target - numbers[i]) != hashmap.end()) { // find函数返回hashmap.end()代表未找到,否则代表找到
// 将结果存入数组
res.push_back(hashmap[target - numbers[i]] + 1);
res.push_back(i + 1);
break;
} else {
hashmap[numbers[i]] = i; // 将未找到的值插入哈希表中,继续遍历
}
}
return res;
}
}; 此解法只遍历数组一次,且在哈希表中查找的时间复杂度为O(1),因此总时间复杂度为O(N);该方法需要构建哈希表,因此空间复杂度为O(N)。



京公网安备 11010502036488号