1. 程式人生 > >LeetCode題解:Two Sum

LeetCode題解:Two Sum

Two Sum

Given an array of integers, find two numbers such that they add up to a specific target number.

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)});
    }
};