Two Sum
遍历一遍数组,建立map,其中key为数组元素,value为对应的index,开始查找,如果目标减去当前值存在,说明找到了,返回两个值的index,否则继续查找,保存新的键值对。
时间复杂度:
O(n)
O
(
n
)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> m;
for (int i = 0; i < nums.size(); ++i) {
if (m.count(target - nums[i])) {
return {i, m[target - nums[i]]};
}
m[nums[i]] = i;
}
return {};
}
};
Two Sum II - Input array is sorted
题目给了一个排序好的数组,因此我们可以用两个指针,一个指向开头,一个指向末尾,然后向中间遍历,如果指向的两个数相加正好等于target的话,直接返回两个指针的位置即可,若小于target,左指针右移一位,若大于target,右指针左移一位,以此类推直至两个指针相遇停止。
要注意题目从index1开始计数,所以记得加1。
时间复杂度:
O(n)
O
(
n
)
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int left = 0;
int right = numbers.size() - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if (sum == target) return {left + 1, right + 1};
else if (sum < target) ++left;
else --right;
}
return {};
}
};
Two Sum III - Data structure design
Design and implement a TwoSum class. It should support the following operations:add and find.
add - Add the number to an internal data structure.
find - Find if there exists any pair of numbers which sum is equal to the value.
For example,
add(1); add(3); add(5);
find(4) -> true
find(7) -> false
哈希表的解法,我们把每个数字和其出现的次数建立映射,然后我们遍历哈希表,对于每个值,我们先求出此值和目标值之间的差值t,然后我们需要分两种情况来看,如果当前值不等于差值t,那么只要哈希表中有差值t就返回True,或者是当差值t等于当前值时,如果此时哈希表的映射次数大于1,则表示哈希表中还有另一个和当前值相等的数字,二者相加就是目标值。
class TwoSum {
public:
void add(int number) {
++m[number];
}
bool find(int value) {
for (auto a : m) {
int t = value - a.first;
if ((t != a.first && m.count(t)) || (t == a.first && a.second > 1)) {
return true;
}
}
return false;
}
private:
unordered_map<int, int> m;
};
Two Sum IV - Input is a BST
只要是两数之和的题,一定要记得用哈希表来做,这道题只不过是把数组变成了一棵二叉树而已,换汤不换药,我们遍历二叉树就行,然后用一个哈希set,在递归函数函数中,如果node为空,返回false。如果k减去当前结点值在哈希set中存在,直接返回true;否则就将当前结点值加入哈希set,然后对左右子结点分别调用递归函数并且或起来返回即可。
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
if (!root) return false;
unordered_set<int> s;
return helper(root, k, s);
}
bool helper(TreeNode* node, int k, unordered_set<int>& s) {
if (!node) return false;
if (s.count(k - node->val)) return true;
s.insert(node->val);
return helper(node->left, k, s) || helper(node->right, k, s);
}
};
我们也可以用层序遍历来做,这样就是迭代的写法了,但是利用哈希表的精髓还是没变的
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
if (!root) return false;
unordered_set<int> s;
queue<TreeNode*> q{{root}};
while (!q.empty()) {
TreeNode* t = q.front(); q.pop();
if (s.count(k - t->val)) return true;
s.insert(t->val);
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
return false;
}
};