原题链接:https://leetcode.com/problems/two-sum/description/
题目很简单,最开始用的是两层循环的暴力求解,对数组中的每一个数都遍历一次数组即可,如下:
Your runtime beats 17.84 % of cpp submissions.
Runtime: 209 ms
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) {
vector<int> result;
result.push_back(i);
result.push_back(j);
return result;
}
}
}
}
};
这种方法时间复杂度是O(n2
)。
另一种方法是通过构建一个哈希表,以减少对数组中每一个数查找complement的时间,如下:
Your runtime beats 81.16 % of cpp submissions.
Runtime: 6 ms
#include <list>
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
list<int> hashTable[10];
int result_i, result_j;
for (int i = 0; i < nums.size(); i++)
hashTable[abs(nums[i] % 10)].insert(hashTable[abs(nums[i] % 10)].begin(), nums[i]);
for (int i = 0; i < nums.size(); i++) {
int key = abs((target - nums[i]) % 10);
for (list<int>::iterator iter = hashTable[key].begin(); iter != hashTable[key].end(); iter++) {
if (*iter + nums[i] == target) {
result_i = i;
for (int j = 0; j < nums.size(); j++) {
if (nums[result_i] + nums[j] == target && j != result_i) {
result_j = j;
vector<int> result;
result.push_back(result_i);
result.push_back(result_j);
return result;
}
}
}
}
}
}
};
通过取模的哈希函数大大降低了查找的时间,但也增加了算法需要的空间。
看了solution之后,发现用了unordered_map,查阅文档后发现,其内部也是用哈希实现的:
Internally, the elements in the unordered_map are not sorted in any particular order with respect to either their key or mapped values, but organized into buckets depending on their hash values to allow for fast access to individual elements directly by their key values (with a constant average time complexity on average).
具体代码如下:
vector<int> twoSum(vector<int> &numbers, int target)
{
//Key is the number and value is its index in the vector.
unordered_map<int, int> hash;
vector<int> result;
for (int i = 0; i < numbers.size(); i++) {
int numberToFind = target - numbers[i];
//if numberToFind is found in map, return them
if (hash.find(numberToFind) != hash.end()) {
//+1 because indices are NOT zero based
result.push_back(hash[numberToFind] + 1);
result.push_back(i + 1);
return result;
}
//number was not found. Put it in the map.
hash[numbers[i]] = i;
}
return result;
}
这种算法在遍历数组将数组元素插入unordered_map的同时,也不断地在回顾已插入unordered_map中的元素是否包含当前要找的complement,最终只使用了一层循环就完成了,算法复杂度为O(n )。