leetCode(2) 數組之和定值的座標

上題:

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。

你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個數組中同樣的元素。(其實我非常不能理解這個重複利用是個啥意思,不能做2次循環遍歷??????)

我很容易想到一個解法,暴力解法:

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((target - nums[i]) == nums[j]){
                    return new int[] {i,j};
                }
            }
        }
        return null;
    }
}

曾經面試的我,遇到一個類似這個求最大值的問題,想起來也是淚,暴力解法,被面試官鄙視了一大通,痛定思痛啊,往事不堪回首,離題了離題了。

暴力解法其實我不知道是不是符合題意中的不能重複利用元素,其實這看起來每個元素除了第一個都被輪慘了。

附上覆雜度

題幹描述中有一句話很重要,就是假設每次只會給出一組答案,也就意味着,這個數組裏是沒有重複元素的,如果有重複元素,必然會導致給出的答案是多組的存在。雞賊啊,這坑挖的。滿足這個條件下,就可以用上傳說中的hashmap用空間換時間的求解法。

附上官方解法:

兩遍hash 法,有人質疑在containsKey(complement) 這個方法中是有遍歷的,會導致複雜度更高,hashMap.containsKey(value)最好情況是O(1),最壞情況是O(n);實際上跟第一種所謂的暴力法幾乎沒啥區別。除非數組內有大量重複的值hash才能體現出優勢,想想其實沒有最完美的解法,但是可以參考大數據量的命中問題。

爲了對運行時間複雜度進行優化,我們需要一種更有效的方法來檢查數組中是否存在目標元素。如果存在,我們需要找出它的索引。保持數組中的每個元素與其索引相互對應的最好方法是什麼?哈希表。

通過以空間換取速度的方式,我們可以將查找時間從 O(n) 降低到 O(1)。哈希表正是爲此目的而構建的,它支持以 近似 恆定的時間進行快速查找。我用“近似”來描述,是因爲一旦出現衝突,查找用時可能會退化到 O(n)。但只要你仔細地挑選哈希函數,在哈希表中進行查找的用時應當被攤銷爲 O(1)。

一個簡單的實現使用了兩次迭代。在第一次迭代中,我們將每個元素的值和它的索引添加到表中。然後,在第二次迭代中,我們將檢查每個元素所對應的目標元素(target - nums[i])是否存在於表中。注意,該目標元素不能是 nums[i]本身!

 public int[] twoSum2(int[] nums, int target){
        Map<Integer,Integer> storeMap = new HashMap<Integer, Integer>();
        for(int i =0;i<nums.length ; i++){
            storeMap.put(nums[i], i);
        }
        for(int j= 0; j< nums.length; j++){
            int complement = target - nums[j];
            //這裏有個特殊的判斷條件,就是這個值不能是自己 也就是 8 -4 =4 ,這樣就出來一個錯誤的結果
            if (storeMap.containsKey(complement) && storeMap.get(complement) != j) {
                return new int[] { j, storeMap.get(complement) };
            }

        }
        return null;
    }

一次hash遍歷

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

本着學習的目的

除了暴力解法,hash解法無法解決重複元素問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章