Introduction
Question:1. 两数之和
解法一
Analysis
解法一:用两个循环来暴力查找,O(n^2)
解法二:一般这种数组的问题,通常可以先排序来把复杂度降低到 O(nlogn)
对于这道题来说,如果数组是有序的,在原来的解法一种的第二层循环就可以用二分查找来优化了,这样时间复杂度就是 O(nlogn) 了。
但是非常尴尬的是,题目要求返回下标,虽然解法二也能做,但是写起来就有点繁琐了。
首先创建一个index数组,按 nums 中的元素只对 index 进行排序
查找时用同样的方法查找,或者用 pair 来做,但是好像区别也不大。由于 Cache 的原因,可能 pair 快一点,但是空间消耗也增加了一倍。下面是用pair实现的版本:
Implement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| vector<int> twoSum(vector<int>& nums, int target) { vector<pair<int, int>> vec; for(int i = 0;i < nums.size(); i++) vec.push_back(make_pair(nums[i], i));
auto cmp = [](auto &p1, auto &p2) { return p1.first < p2.first; }; sort(vec.begin(), vec.end(), cmp); auto tp = make_pair(target, -1); for(auto beg = vec.begin(); beg != vec.end(); beg++) { tp.first = target - beg->first; auto it = lower_bound(beg + 1, vec.end(), tp, cmp); if (it != vec.end() && it->first == tp.first) { return {beg->second, it->second}; } } return {}; }
|
解法二
Analysis
由于传入数组的大小最多才到 10^3,所以我们可以用时间换空间,利用使用HastMap来解这道题。具体的操作如下:
遍历整个数组,一边遍历一边将数组元素作为 key ,下标作为 value 插入到 HashMap 中,当遍历到第 i 个元素时,我们用 HashMap 快速的判断已经遍历过的元素中是否存在 target - nums[i]。
Implement
1 2 3 4 5 6 7 8 9 10 11
| vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> imap; for (int i = 0;i < nums.size(); i++) { auto it = imap.find(target - nums[i]); if (it != imap.end()) { return {i, it->second}; } imap[nums[i]] = i; } return {}; }
|
One More Thing