The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
思路:
首先考虑题目中的数组没有排序。那么采用暴力搜索的话,时间复杂度O(n^2) = n(n-1)。
当然,遇到搜索问题,一般考虑的是排序处理。如果数组经过排序的话,那么可以想到,采用两个指针分别在数组的前后。如果指针对应数的和大于target,则右边指针左移;反之左边指针右移,直到找到解为止(题目条件给出必然有解)。这样是一个时间复杂度为O(n)的操作,配合时间复杂度O(n log n)的排序,总共时间复杂度是O(n log n)。这里需要考虑排序前后数组序数的对应问题。这个可以采用operator overload来处理。
对排序后数组的另外一个思路是一个指针从左向右移动,用二分搜索寻找指向数值与target之间的差值(这个可以用std::lower_bound实现)。如果没有找到,则lower_bound给出的迭代器是下一次搜索的终点。整个计算的时间复杂度仍然是O(n log n)。
题解:
这里编码使用了C++11标准。其中begin和end是C++11 STL中取容器的起点和终点迭代器的新函数。auto在C++11中改为自动推断变量类型,原来和register对应的语义消失。for这里是新的range-based for。sort中的第三个参数是lambda函数。最后使用了initializer_list初始化返回的vector。
class Solution { public: typedef pair<int, size_t> valoffset_pair_t; vector<int> twoSum(vector<int> &numbers, int target) { vector<valoffset_pair_t> new_array; // Preallocate the memory for faster push_back new_array.reserve(numbers.size()); // generate the new array int index=0; for(auto i : numbers) new_array.push_back(valoffset_pair_t(i, ++index)); // Note: here the index is already increased, so // the new indices are not zero based // sort it! sort(begin(new_array), end(new_array), [&](const valoffset_pair_t& v1, const valoffset_pair_t& v2) -> bool { return v1.first < v2.first; } ); // now find the right pair using two pointers auto p_left=begin(new_array); auto p_right=end(new_array); p_right--; // make it locate at the last position int sum = p_left->first + p_right->first; // it is guaranteed to have one exact solution while(sum!=target) { sum = p_left->first + p_right->first; if (sum > target) p_right--; else if (sum < target) p_left++; else break; } return vector<int>( {min(p_left->second, p_right->second), max(p_left->second, p_right->second)}); } };