[LeetCode] 1. Two Sum 兩數之和


 

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 [0, 1].

 

啦啦啦,歡迎開啟 LeetCode 刷題的旅程,這將是一段漫長而又艱辛的旅程,這是一條攀登珠穆朗瑪的皚皚雪山路,這是通向 One Piece 寶藏的偉大航路,這是成為火影的無比殘酷的修羅場,這是打破吊絲與高富帥之間界限的崩玉。但請不要害怕,在老船長 Grandyang 博主的帶領下,必將一路披荊斬棘,將各位帶到成功的彼岸,不過一定要牢記的是,不要下船,不要中途放棄,要堅持,要自我修煉,不斷成長!那么,起航吧~這道 Two Sum 的題目作為 LeetCode 的開篇之題,乃是經典中的經典,正所謂‘平生不識 TwoSum,刷盡 LeetCode 也枉然’,就像英語單詞書的第一個單詞總是 Abandon 一樣,很多沒有毅力堅持的人就只能記住這一個單詞,所以通常情況下單詞書就前幾頁有翻動的痕跡,后面都是嶄新如初,道理不需多講,雞湯不必多灌,明白的人自然明白。

這道題給了我們一個數組,還有一個目標數target,讓找到兩個數字,使其和為 target,乍一看就感覺可以用暴力搜索,但是猜到 OJ 肯定不會允許用暴力搜索這么簡單的方法,於是去試了一下,果然是 Time Limit Exceeded,這個算法的時間復雜度是 O(n^2)。那么只能想個 O(n) 的算法來實現,由於暴力搜索的方法是遍歷所有的兩個數字的組合,然后算其和,這樣雖然節省了空間,但是時間復雜度高。一般來說,為了提高時間的復雜度,需要用空間來換,這算是一個 trade off 吧,但這里只想用線性的時間復雜度來解決問題,就是說只能遍歷一個數字,那么另一個數字呢,可以事先將其存儲起來,使用一個 HashMap,來建立數字和其坐標位置之間的映射,由於 HashMap 是常數級的查找效率,這樣在遍歷數組的時候,用 target 減去遍歷到的數字,就是另一個需要的數字了,直接在 HashMap 中查找其是否存在即可,注意要判斷查找到的數字不是第一個數字,比如 target 是4,遍歷到了一個2,那么另外一個2不能是之前那個2,整個實現步驟為:先遍歷一遍數組,建立 HashMap 映射,然后再遍歷一遍,開始查找,找到則記錄 index。代碼如下:

 

C++ 解法一:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> m;
        vector<int> res;
        for (int i = 0; i < nums.size(); ++i) {
            m[nums[i]] = i;
        }
        for (int i = 0; i < nums.size(); ++i) {
            int t = target - nums[i];
            if (m.count(t) && m[t] != i) {
                res.push_back(i);
                res.push_back(m[t]);
                break;
            }
        }
        return res;
    }
};

  

Java 解法一:

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
        int[] res = new int[2];
        for (int i = 0; i < nums.length; ++i) {
            m.put(nums[i], i);
        }
        for (int i = 0; i < nums.length; ++i) {
            int t = target - nums[i];
            if (m.containsKey(t) && m.get(t) != i) {
                res[0] = i;
                res[1] = m.get(t);
                break;
            }
        }
        return res;
    }
} 

 

或者可以寫的更加簡潔一些,把兩個 for 循環合並成一個:

 

C++ 解法二:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> m;
        for (int i = 0; i < nums.size(); ++i) {
            if (m.count(target - nums[i])) {
                return {i, m[target - nums[i]]};
            }
            m[nums[i]] = i;
        }
        return {};
    }
};

 

Java 解法二:

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
        int[] res = new int[2];
        for (int i = 0; i < nums.length; ++i) {
            if (m.containsKey(target - nums[i])) {
                res[0] = i;
                res[1] = m.get(target - nums[i]);
                break;
            }
            m.put(nums[i], i);
        }
        return res;
    }
}

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1

 

類似題目:

4Sum

3Sum Smaller

3Sum Closest

3Sum

Two Sum III - Data structure design 

Two Sum II - Input array is sorted 

 

參考資料:

https://leetcode.com/problems/two-sum/

https://leetcode.com/problems/two-sum/discuss/3/Accepted-Java-O(n)-Solution

https://leetcode.com/problems/two-sum/discuss/13/Accepted-C++-O(n)-Solution

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2024 CODEPRJ.COM