從零打卡leetcode之day 1--兩數之和

帥地發表於2018-08-13

前言

就是要把leetcode的題刷完,每天一道題,每天進步一點點


從零打卡leetcode之day 1

題目描述:
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。
你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。

示例:
給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

看到這道題的第一想法,暴力暴力,能用暴力解決的事情不要和我談其他。

於是,兩個for迴圈噼裡啪啦。

    //方法一:簡單暴力,兩個for迴圈搞定
    public int[] twoSum1(int[] nums, int target) {
        int[] temp = new int[2];//用來存要找的數的下標
        for(int i = 0; i < nums.length; i++){
            for(int j = i + 1; j < nums.length; j++){
                if(nums[i] + nums[j] == target){
                    temp[0] = i;
                    temp[1] = j;
                    return temp;
                }
            }
        }
        return null;
    }

不過心裡才兩個迴圈時間複雜度可是n的平方,心想肯定得超時,不過還是大膽提交一下提交,呵呵,居然通過了。。。。

我猜這可能是第一道題的原因,讓我們開心一下。不過排名你懂的。

不過居然要刷題,要學習演算法,那麼肯定是不能滿足於「第一想法」的,必須得找出我們自己能接受的最優解。

於是我想到了用空間換時間,就是我們可以用雜湊表對映的方法,先把陣列裡所有元素的值作為key,下標作為value存進hashmap裡,我們知道從hashmap裡查詢元素的時間複雜度近似常數,即O(1)。然後我們可以用一個for迴圈來遍歷陣列,遍歷的過程中一邊查詢另一個數是否在hashMap裡,例如a = nums[i],然後查詢b = targert - a是否在hashMap裡,如果在,則證明a,b便是要找的數,否則繼續查詢。程式碼下:

public int[] twoSum2(int[] nums, int target){
        int[] temp = new int[2];
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i], i);
        }
        //遍歷查詢
        for(int i = 0; i < nums.length; i++){
            int a = nums[i];
            if(map.containsKey(target - a)){
                temp[0] = i;
                temp[1] = map.get(target - a);
                return temp;
            }
        }
        return null;
    }

不過,不知道大家發現問題了沒有,題目裡只是說會有唯一解,並且一個元素只能用一次,但並沒有說,不能兩個元素的值相同,也就是說,陣列如果有元素的值相同的話,存進hashMap會出現衝突的情況。所以,這樣先把陣列的所有元素存進hashMap的做法是不嚴謹的。

我們來分析一下處理方法:

出現這個問題的本質原因是因為我們要找的那兩個數剛好相等,導致我們當今雜湊表的時候出現了丟失的情況。如何解決?

上面說了,問題的原因是這兩個我們要的數剛好相等,並且我們從一開始就想把他們兩個硬塞進雜湊表裡,導致一山容不了二虎。其實,我們可以換一種想法啊,我們可以一邊遍歷查詢一邊把數放進雜湊表裡啊。
先看程式碼:

public int[] twoSum3(int[] nums, int target){
        int[] temp = new int[2];
        Map<Integer,Integer> map = new HashMap<>();
        //遍歷查詢
        for(int i = 0; i < nums.length; i++){
            int a = nums[i];
            if(map.containsKey(target - a)){
                temp[0] = map.get(target - a);
                temp[1] = i;
                return temp;
            }else {//如果找不到則存進去
                map.put(nums[i], i);
            }
        }
        return null;
    }

就是取出數a=nums[i],先判斷b=target-a在不在雜湊表裡,如果在,那麼a和b就是要找的值了,如果不在,就把a放進雜湊表了。
這樣,就不會出現上面那種情況的衝突了,因為兩個我們要找的數,只有一個會放在雜湊表裡。


相關文章