两数之和
给定一个整数数组nums
和一个整数目标值target
,请你在该数组中找出和为目标值target
的那两个整数,并返回它们的数组下标。
- 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
- 你可以按任意顺序返回答案。
1.暴力法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { int i, j; for (i = 0; i < nums.size(); ++i) { for (j = i + 1; j < nums.size(); ++j) { if (nums[i] + nums[j] == target) { return {i, j}; } } } return {i, j}; } };
|
2.二分查找
思想:sort排序 + 二分查找
使用for循环遍历数组中的每一个数字
在for循环内部,使用target值减去当前遍历的数字值获取配对值ret,使用二分查找该数字ret
如果找到该数字则直接输出其下标(初始若有序的情况下)
实际是无序的!难点在于如何联系被sort打乱下标后的vec与未打乱的nums,并从其中找出目标数字的下标?
1 2 3 4
| for (int j = 0; j < n; j++) { if (nums[j] == vec[i] || nums[j] == ret) result.push_back(j); if(result.size() == 2) return result; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> vec; int n = nums.size(); for (auto &temp: nums) { vec.push_back(temp); } sort(vec.begin(), vec.end()); for (int i = 0; i < n; i++) { int ret = target - vec[i]; int idx = lower_bound(vec.begin(), vec.end(), ret) - vec.begin(); if(0 <= idx && idx < n && vec[idx] == ret) { vector<int> result; for (int j = 0; j < n; j++) { if (nums[j] == vec[i] || nums[j] == ret) result.push_back(j); if(result.size() == 2) return result; } } } return {}; } };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> vec; for (auto &temp: nums) { vec.push_back(temp); } sort(vec.begin(), vec.end()); for (int i = 0; i < vec.size(); ++i) { int ret = target - vec[i]; int l = i + 1; int r = vec.size() - 1; while (l <= r) { int mid = (l + r) / 2; if (ret == vec[mid]) { vector<int> result; for (int j = 0; j < vec.size(); ++j) { if (nums[j] == vec[i] || nums[j] == ret) result.push_back(j); if(result.size() == 2) return result; } } if (ret < vec[mid]) { r = mid - 1; } else { l = mid + 1; } } } return {}; } };
|
3.双指针
思想:sort排序 + 双指针法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> vec; for (auto &temp: nums) { vec.push_back(temp); } sort(vec.begin(), vec.end()); int l = 0; int r = vec.size() - 1; while (l < r) { int sum = vec[l] + vec[r]; if (sum == target) { vector<int> result; for (int i = 0; i < nums.size(); i++) { if (nums[i] == vec[r] || nums[i] == vec[l]) result.push_back(i); if(result.size() == 2) return result; } } if (sum > target) { --r; } else { ++l; } } return {}; } };
|
4.哈希表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { map<int,int> hashmap; vector<int> result(2,-1); for (int i = 0; i < nums.size(); i++) { hashmap.insert(map<int, int>::value_type(nums[i], i)); } for (int i = 0; i < nums.size(); i++) { if(hashmap.count(target - nums[i]) > 0 && (hashmap[target - nums[i]] != i)) { result[0] = i; result[1] = hashmap[target - nums[i]]; break; } } return result; }; };
|
哈希表优化(减少for循环次数):
- 在进行迭代将元素插入到表中的同时,就可以马上进行检查,表中是否已经存在当前元素所对应的目标元素
- 如果存在,那我们已经找到了对应解,并立刻将其返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { map<int, int> hashmap; vector<int> result(2,-1); for(int i = 0; i < nums.size(); ++i) { if (hashmap.count(target - nums[i]) > 0) { result[0] = hashmap[target - nums[i]]; result[1] = i; break; } else { hashmap[nums[i]] = i; } } return result; }; };
|