LeetCode OJ的第一題,如果有問題或者給我指點歡迎來信討論[email protected]

題目描述

LeetCode OJ的第一題,題目描述如下:

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.


給定一個序列,若其中存在兩個元素之和為給定的數字target。注意返回的兩個序列要求“not zero-based”,也就是從1開始計數而不是像陣列一樣從0下標開始。

思路1

首先給定的序列是無序的,如果序列有序(設已經從小到大排序),那麼設一個下標A從頭開始,另一個下標B從尾開始,如果二者之和小於target,說明兩者的和不夠大,由於B下標指向的是當前可能情況下序列的最大值(因為B開始指向最大值,而B的每次減小都是因為B加上當前可能情況下序列最小的值已經超過了target),所以下標A增加,如果二者之和等於target,則得到所需結果。如果二者之和大於target,說明二者之和大了,由於A下標指向的是當前可能情況下序列的最小值(因為A開始指向最小值,而A的每次增加都是因為A加上當前可能情況下序列的最大值已經不夠target),所以下標B減小。.
這種方法在兩個下標遍歷的時候只有O(n)的複雜度,但是在排序時候要O(nlgn)複雜度,所以總的複雜度為O(nlgn)。

思路2

上面思路的瓶頸在於排序,能否不需要排序而直接找到結果呢?
如果存在著一對解m, n,設m在序列中排在n的前面。我們從頭到尾遍歷該序列,用資料結構S儲存已經遍歷過的資料。遍歷到m時候,尋找target-m是否在S中,這時候還是不在。但是遍歷到n的時候就發現target-n,也就是m,在S中,這時候我們就得到了解。該方法的時間複雜度為O(n),但是可能需要額外O(n)的儲存空間。而資料結構要很方便於查詢,所以使用了字典(C++中用map,Python中用dict,儲存資料以及下標),查詢複雜度為O(1)。

注意事項

返回的值前一個要比後一個小。
要注意存在著兩個元素相同的情況,如4,4,target=8。這時候不要返回相同的下標

程式碼

Python, O(nlgn)
def twoSum(self, num, target):
        tmp_num = num[:]
        tmp_num.sort()
        index1 = 0
        index2 = len(tmp_num)-1
        while index1 < index2:
            tmp_target = tmp_num[index1] + tmp_num[index2]
            if tmp_target == target:
                break
            elif tmp_target > target:
                index2 -= 1
            else:
                index1 += 1
        if index1 == index2:
            return (-1, -1)
        else:
            ans1 = num.index(tmp_num[index1])
            ans2 = num.index(tmp_num[index2])
            if ans2 != ans1:
                # not zero based
                return (min(ans1, ans2)+1, max(ans1, ans2)+1)
            else:
                ans2 = num[ans1+1:].index(tmp_num[index2])
                return (ans1+1, ans1+1+ans2+1)

Python,O(n)
def twoSum1(self, num, target):
        tmp_num = {}
        for i in range(len(num)):
            if target - num[i] in tmp_num:
                # here do not need to deal with the condition i = target-i
                return (tmp_num[target-num[i]]+1, i+1)
            else:
                tmp_num[num[i]] = i
        return (-1, -1)

C++,O(n)
class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        map<int, int> searched;
		vector<int> res;
		for (int i = 0; i < numbers.size(); ++i){
			if (searched.count(target - numbers[i])){
				res.push_back(searched[target - numbers[i]]+1);
				res.push_back(i+1);
				return res;
			} else {
				searched[numbers[i]] = i;
			}
		}
		res.push_back(-1);
		res.push_back(-1);
		return res;
    }
};