01 two sum
1. 题目描述
在一个数组中找两个数,让这两个数的和等于目标值target。
要求:这两个数任意一个不可以重复使用 即a 不能再找a进行相加
2. 题解
2.1 解法一:暴力解法
思路:
用第一层循环遍历第一个数,用第二层循环遍历第二个数,由于不可以重复,所以取第一个数后面的那个数。
判断两个数的和是否等于目标值,如果等于,则返回两个数的下标,如果不等于,则进行下次循环判断
// brute solution
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (nums[i] + nums[j] == target) {
result.push_back(i);
result.push_back(j);
return result;
}
}
}
return result;
}
};
算法复杂度: O ( n 2 ) O(n^2) O(n2)
2.2 哈希解法
思路:
改进暴力解法,那改进的想法是什么呢?那就是尽可能的寻找题目条件。这道题的隐藏条件是如果我找到第一个数a,那么第二数其实已经知道需要找什么了 即target - a
而知道找什么,就可以做改进。那怎么改呢? 提高找的效率,那最好是哈希了,因为算法复杂度是 O ( 1 ) O(1) O(1) ,所以第二个数可以通过构建哈希表来实现第二个数的命中
正常思路是先将数组中的数进行哈希映射,即哈希的key是数组中的值value 而value是值的index,因为最后返回的是index
然后再去遍历,但是要避免重复。比如: 3,3 这个数组, target是6
先去构造哈希:
3 -> 0
3 -> 1
当a取3的时候,要找的第二个值b= 6-3 = 3 这时候就存在重复,因为命中的index是0 ,而题目要求是不可以重复元素的
所以需要加一个判断条件,即b的下标不等于a的下标
class Solution{
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
unordered_map<int, int> table; // key : value value : index
// generate a hashtable
for (int i = 0; i < nums.size(); i++) {
table[nums[i]] = i;
}
for (int i = 0; i < nums.size(); i++) {
int a = nums[i];
int find_value = target - a;
auto re = table.find(find_value);
if (re!=table.end()) { // find it
if (re->second == i) {
continue;
}
result.push_back(i);
result.push_back(re->second);
return result;
}
}
return result;
}
};
算法复杂度: O ( n ) O(n) O(n)
2.3 解法三:一个小技巧
如何优化重复元这个写法?
采用了边遍历边构建的方式进行构造哈希表
class Solution{
public:
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];
auto re = hash.find(numberToFind);
if (re != hash.end()) {
result.push_back(i);
result.push_back(re->second);
return result;
}
//number was not found. Put it in the map.
hash[numbers[i]] = i;
}
return result;
}
};
算法复杂度: O ( n ) O(n) O(n)
3. 视频讲解
[LeetCode] 01-two sum
4. 总结
- c++中使用unordered_map来做哈希
- 哈希的构造可以边遍历边构造