給定一個整數數組 nums
和一個目標值 target
,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。java
你能夠假設每種輸入只會對應一個答案。可是,你不能重複利用這個數組中一樣的元素。node
示例:數組
給定 nums = [2, 7, 11, 15], target = 9 由於 nums[0] + nums[1] = 2 + 7 = 9 因此返回 [0, 1]
官方解答:
public int[] twoSum(int[] nums, int target) { 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 complement = target - nums[i]; if (map.containsKey(complement) && map.get(complement) != i) { return new int[] { i, map.get(complement) }; } } throw new IllegalArgumentException("No two sum solution"); }
官方這樣的作法時間複雜度是o(n),可是for循環裏帶containKey怎麼會是o(n)呢?指針
原來map.containKey()的複雜度能夠看作o(1):code
if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { // 直接命中 if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; // 未命中 if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } }
1. 指針first指向那一行數組的引用(那一行數組是經過table下標範圍n-1和key的hash值計算出來的),若命中,則經過下標訪問數組,時間複雜度爲O(1)
2. 若是沒有直接命中(key進行hash時,產生相同的位運算值),存儲方式變爲紅黑樹,那麼遍歷樹的時間複雜度爲O(n)。
blog
另外,由於hashMap以key存hash,value是根據key所得。因此containValue()的時間複雜度爲O(n),和containKey()不一樣。get