描述
給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。
你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個數組中同樣的元素。
示例:
給定 nums = [2, 7, 11, 15], target = 9
因爲 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
難度:簡單
一、暴力法
思路
直接進行循環,因爲有唯一答案,那麼有結果時直接return即可
代碼
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int x = 0;x < nums.length-1;x++){
for(int y = x+1;y<nums.length;y++){
if(nums[x] + nums[y] == target) return new int[]{x,y};
}
}
return new int[]{};
}
}
複雜度分析
時間複雜度:O(n^2)
對於每個元素,我們試圖通過遍歷數組的其餘部分來尋找它所對應的目標元素,這將耗費 O(n) 的時間。因此時間複雜度爲O(n^2)
空間複雜度:O(1)
二、兩遍Hash表算法
思路
這個方法時典型的空間換取時間算法
我們在暴力法中,連續進行了兩次遍歷查找,導致時間複雜度成爲O(n^2),引入Hash表可以將遍歷的時間複雜度變爲O(1)
這種方法巧用了HashMap中對Key的操作,我們將數組內的值放到key上,下標放到value上,通過計算key值來得到是否map中有我們需要的另一個值,如果有,那麼獲取到那個key所對應的value,也就是得到了我們在數組中的下標
有一點需要注意的是,在條件判斷是否存在該值的時候,應添加去重判斷,舉例:target = 6,數組中某值等於3(有且僅有一個),此時去查找key,肯定會返回一個有一個值與當前值之和等於6,但是這不是我們要找的值,此時會返回{x,x}
代碼
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> intMap = new HashMap();
for (int i = 0; i < nums.length; i++) {
intMap.put(nums[i], i);
}
for (int i = 0; i < intMap.size(); i++) {
int complement = target - intMap.get(i);
if (intMap.containsKey(complement) && intMap.get(complement) != i) return new int[]{i, intMap.get(complement)};
}
return new int[]{};
}
}
複雜度分析:
時間複雜度:O(n),我們把包含有 n 個元素的列表遍歷兩次。由於哈希表將查找時間縮短到O(1) ,所以時間複雜度爲 O(n)
空間複雜度:O(n),所需的額外空間取決於哈希表中存儲的元素數量,該表中存儲了 n 個元素。
三、一遍Hash算法
思路
我們遍歷數組時,每往hash中添加一個元素,我們就可以拿當前元素獲取差值,並與hash中已經存在的元素進行對比,如果有滿足條件的key,就可以直接返回,這樣就只需要一次遍歷就可以完成所有操作
代碼
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> intMap = new HashMap();
for (int i = 0; i < nums.length; i++) {
intMap.put(nums[i], i);
int com = target - nums[i];
if (intMap.containsKey(com) && intMap.get(com) != i) return new int[]{intMap.get(com),i};
}
return new int[]{};
}
}
複雜度分析:
時間複雜度:O(n),我們只遍歷了包含有 n 個元素的列表一次。在表中進行的每次查找只花費 O(1) 的時間。
空間複雜度:O(n),所需的額外空間取決於哈希表中存儲的元素數量,該表最多需要存儲 n 個元素。
四、總結
1.空間換區時間
2.巧用hash表
3.積累知識,打開思路