LeetCode 第一題,Two Sum,leetcodetwosum

來源:互聯網
上載者:User

LeetCode 第一題,Two Sum,leetcodetwosum

今天早上起來去機房的路上還在想,一直不做演算法題老是覺得不踏實。做做題總是讓自己覺得自己真的在做做學習。。。。


這也算是一種強迫症吧。

那就從今天開始做做LeetCode,因為好久沒做過了,所以第一題還是看了別人的題解和思路,算是找找感覺。


總的來說第一題是個水。。。。



題目還原

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

中文意思就是給你一個整數數組和一個目標值,找出這個數組中的兩個元素的和為該目標值的元素的下標,輸出為index1和index2,按從小到大的序輸出。且假定每個數組都恰好包含一個解,即使,恰好每個給定的數組都有且只有一種符合的結果。

解答

首先,做這種的題目一般都是需要排序的,為了速度,也為了方便尋找。

當然,不排序也可以做,,不過那個複雜度貌似有點不合理。

雖然給定的數組不是按序給定的,但是,我們要知道,在這個演算法的世界裡面,有序的話,一切都很簡單了。

有序的價值啊。可惜我的生活現在還是有些混亂無章。。。。

但是因為最後要返回的是原數組的元素下標,因此,我們必須要在使用原數組的空間做一個副本。。。。

然後就是打副本,首先假設副本是從小到大,至於怎麼打,我想到一種方法:

選取左右兩個遊標,取二者之和,若和等於目標值,將這個所代表的元素在原數組尋找確定下標,然後儲存在index中。留待返回。

若和大於目標值,則讓右下標往左移;

若和小於目標值,則讓左下標往右移。

直至左右相等之前為止。

因此實現的代碼如下:

/*************************************************************************> File Name: twosum.cpp> Author: SuooL> Mail: 1020935219@qq.com> Created Time: 2014年07月31日 星期四 20時14分32秒************************************************************************/class Solution{    public:    vector<int> twoSum(vector<int> &numbers, int target)    {        // Note: The Solution object is instantiated only once and is reused by each test case.        vector<int> num = numbers;        std::sort(num.begin(), num.end());        int length = numbers.size();        int left = 0;        int right = length - 1;        int sum = 0;        vector<int> index;        while(left < right)        {            sum = num[left] + num[right];            if(sum == target)            {                // find the index from the old array                for(int i = 0; i < length; ++i)                {                    if(numbers[i] == num[left])                    {                        index.push_back(i + 1);                    }                    else if(numbers[i] == num[right])                    {                        index.push_back(i + 1);                    }                    if(index.size() == 2)                    {                        break;                    }                }                break;            }            else if(sum > target)            {                --right;            }            else            {                ++left;            }        }        return index;    }};

Python代碼:

#!/usr/bin/env python# coding=utf-8class Solution:    # @return a tuple, (index1, index2)    def twoSum(self, num, target):             numbers = sorted(num)        length = len(num)        left = 0        right = length - 1        index = []        while left < right:             sums = numbers[left] + numbers[right]            if sums == target:                for i in range(length):                    if num[i] == numbers[left]:                        index.append(i + 1)                    elif num[i] == numbers[right]:                        index.append(i + 1)                                        if len(index) == 2:                        break                break            elif sums > target:                right -= 1            else:                left += 1        result = tuple(index)        return result
下面的一個類似的解法是網路上的,用了最新的C++11標準。表示膜拜。

/*************************************************************************> File Name: twosum_c11.cpp> Author:SuooL > Mail: 1020935219@qq.com> Created Time: 2014年07月31日 星期四 20時18分45秒************************************************************************/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)});    }};

同時,最後看到了,只用了O(n)的hashmap方法,思路是迴圈一次,每次都判斷當前數組索引位置的值在不在hashtable裡,不在的話,加入進去,key為數值,value為它的索引值;在的話,取得他的key,記為n(此時n一定小於迴圈變數i),接下來再在hashtable中尋找(target-當前數值)這個數,利用了hashtable中尋找元素時間為常數的優勢,如果找到了就結束,此處需要注意的是,如果數組中有重複的值出現,那麼第二次出現時就不會加入到hashtable裡了,比如3,4,3,6;target=6時,當迴圈到第二個3時,也可以得到正確結果。

代碼如下:

class Solution {public:    vector<int> twoSum(vector<int> &numbers, int target) {        int i, sum;        vector<int> results;        map<int, int> hmap;        for(i=0; i<numbers.size(); i++){// if the number doesn`t existed in the hashtable            if(!hmap.count(numbers[i]))     {// insert the number and its index                hmap.insert(pair<int, int>(numbers[i], i));            }// find the number which equal to target - numbers[i]            if(hmap.count(target-numbers[i])){                int n=hmap[target-numbers[i]];                if(n<i){                    results.push_back(n+1);                    results.push_back(i+1);                    //cout<<n+1<<", "<<i+1<<endl;                    return results;                }            }        }        return results;    }};

Python:

class Solution:# @return a tuple, (index1, index2)def twoSum(self, num, target):length = len(num)index = []hash_tab = {}for i in range(length):if( not hash_tab.has_key(num[i])) :pair = {num[i] : i}hash_tab.update(pair)if( hash_tab.has_key(target - num[i] )) :n = hash_tab[target-num[i]]if n< i :index.append(n + 1)index.append(i + 1)result = tuple(index)return resultreturn result

Summary首先想到的就是兩層遍曆法,但是顯然時間複雜度太高,是O(N^2),不符合要求.於是就應該想如何降低複雜度,首先應該想將逐個比較轉變為直接尋找,即首先計算出 target與當前元素的差,然後在序列中尋找這個差值,這樣首先就把問題簡化了,而尋找的過程可以先對序列進行快排,然後二分尋找,這樣整體的複雜度就降低為 O(N*logN) 了;尋找最快的方法是利用一個 map容器儲存每個元素的索引,這樣取得某個特定元素的索引只需要常數時間即可完成,這樣就更快了,最多隻需遍曆一次序列,將元素及其索引加入map中,在遍曆的過程中進行對應差值的尋找,如果找到了就結束遍曆,這樣時間複雜度最多為 O(N),It's amazing!
總之,這是自己做的第一道leetcode題,感覺比其他oj要嚴格一些,比如這題有嚴格的執行時間要求,O(N^2)的不能過,可以給自己最佳化程式的理由。繼續加油!
提交記錄:


C C++ leetcode 總是說編譯錯誤,關鍵我連第77行都沒有,只有那幾行……

leetcode都不能自己定義主函數的
需要你構造一個Solution的類

77行redefine的main恰好就是leetcode用來測試你寫的Solution的main函數
 
2014鹽城市英語三模答案 第一題是:what are the two speakers talking about?

這兩人在說什嗎?
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.