1. 程式人生 > >【LeetCode】01 Two Sum與HashMap

【LeetCode】01 Two Sum與HashMap

給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。

你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

解法1:暴力求解

class Solution {
    public int[] twoSum(int[] nums, int target) {
        for (int i = 0;i < nums.length;i++){
            for (int j = i + 1;j < nums.length;j++){
                if (nums[i] + nums[j] == target){
                    return new int[]{i,j};
                }
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

解法2:利用HashMap

  • 解法1的問題是,我們最後要的答案是陣列的下標,而在陣列中我們只能通過下標訪問到元素。
  • 如果我們只能通過下標訪問到元素,我們需要對每對可能出現的值對組合進行遍歷,那麼最後時間複雜度必然是O(n^2)
  • 而如果我們可以通過元素訪問下標,遍歷一遍陣列,對於每個元素,都只需要進行一個操作:在已檢查過的元素裡查詢是否有符合條件的元素,找到則返回它的下標

換句話說,這道題的思路其實只有一種:對每一個數組中的元素,查詢某條件下的另一元素的下標
第一個迴圈,兩種方法是一致的,所以至少O(n)
陣列:我知道我有一堆元素,我不知道他們是啥。查詢的思路孜然是再遍歷一次之前的陣列元素,找到目標元素。
HashMap:我知道我有什麼元素。那麼我既然知道你要找的陣列元素大小是多少,直接檢視鍵值對裡有沒有這個鍵就好了。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        int i;
        int complement;
        for (i = 0;i < nums.length;i++){
            complement = target - nums[i];
            if(map.containsKey(complement)){
                return new int[] {map.get(complement), i};
            }
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("!!!");
    }
}

這道題的目的在於,告訴我們有一種資料結構(Map)可以實現兩種結構間的一對一訪問,而其中的佼佼者,叫做HashMap(用TreeMap試驗了一下,速度比HashMap慢,時間複雜度應該是O(nlogn))