问题:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [1, 2].
思路:
大致有三种方法:
- hash: 从左向右扫描一遍,然后将数及坐标存到map中。然后再扫描一遍即可。时间复杂度 \( O(n) \)
- 双指针扫描: 将数组排序,然后双指针从前后往中间扫描。时间复杂度 \( O(n log(n)) \). 因为要求返回原数组的下标,所以在排序的时候还得有额外的数组来存储下标信息。
- 暴力搜索: 时间复杂度 \( O(n^2) \)
Code 1
1 #include <vector> 2 #include <unordered_map> 3 #include <iostream> 4 #include <algorithm> 5 6 using std::vector; 7 using std::unordered_map; 8 using std::cout; 9 using std::endl; 10 11 // this method we first build the hashmap, then find the result 12 vector<int> two_sum_clumsy(const vector<int> &nums, const int target) { 13 unordered_map<int, int> m; 14 vector<int> result(2, 0); 15 for (int i = 0; i < nums.size(); ++i) { 16 m[nums[i]] = i; 17 } 18 for (int j = 0; j < nums.size(); ++j) { 19 if (m.find(target - nums[j]) != m.end() && m[target - nums[j]] != j) { 20 result[0] = j + 1; // do not forget +1 to j 21 result[1] = m[target - nums[j]] + 1; 22 return result; 23 } 24 } 25 cout << "Not exist!" << endl; 26 return result; 27 }
Code 2
1 // this method is also based on the hashmap, but we build the hashmap and find the result simutaneously 2 // this method is a bit tricky. First, we traverse the array one by one, then we just put the `target-num[i]`(not `num[i]`) into the map. 3 // So, when we checking the next num[i], if we found it is exisited in the map, it means we found the second one. 4 vector<int> two_sum(const vector<int> &nums, const int target) { 5 unordered_map<int, int> m; 6 vector<int> result; 7 8 for (int i = 0; i < nums.size(); ++i) { 9 // not found the second one 10 if (m.find(nums[i]) == m.end()) { 11 // store the first one poisition into the second one's key 12 m[target - nums[i]] = i; 13 } 14 else { 15 // found the second one 16 result.push_back(m[nums[i]] + 1); 17 result.push_back(i + 1); 18 break; 19 } 20 } 21 return result; 22 }
Code 3
1 // this method first sort then find, complexity O(log n) 2 struct Node 3 { 4 int val; 5 int index; 6 Node(int pVal, int pIndex) : val(pVal), index(pIndex) {} 7 }; 8 9 bool compare(const Node &left, const Node &right) { 10 return left.val < right.val; 11 } 12 13 vector<int> two_sum_sorted(const vector<int> &nums, int target) { 14 vector<Node> elements; 15 for (int i = 0; i < nums.size(); ++i) { 16 elements.push_back(Node(nums[i], i)); 17 } 18 // pay attention to the usage to the following sort function in <algorithm> 19 std::sort(elements.begin(), elements.end(), compare); 20 int s = 0, t = elements.size() - 1; 21 vector<int> result; 22 while (s < t) { 23 int temp_sum = elements[s].val + elements[t].val; 24 if (temp_sum == target) { 25 result.push_back(elements[s].index + 1); 26 result.push_back(elements[t].index + 1); 27 std::sort(result.begin(), result.end()); 28 return result; 29 } 30 else if (temp_sum > target) { 31 --t; 32 } 33 else { 34 ++s; 35 } 36 } 37 return result; 38 }
Code 4
1 // this method is the most tedious (这个方法是最麻烦的) 2 vector<int> two_sum_tedious(const vector<int> &nums, const int target) { 3 vector<int> result; 4 for (int i = 0; i < nums.size(); ++i) { 5 for (int j = i + 1; j < nums.size(); ++j) { 6 if (nums[i] + nums[j] == target) { 7 result.push_back(i + 1); 8 result.push_back(j + 1); 9 return result; 10 } 11 } 12 } 13 return result; 14 }