問題描述
倆數之和:
給定一個整數數組 nums 和一個整數目標值 target,請你在該數組中找出 和為目標值 target 的那 兩個 整數,并返回它們的數組下標。你可以假設每種輸入只會對應一個答案,并且你不能使用兩次相同的元素。你可以按任意順序返回答案。
示例 1:
輸入:nums = [2,7,11,15], target = 9
輸出:[0,1]
解釋:因為 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
輸入:nums = [3,2,4], target = 6
輸出:[1,2]
示例 3:
輸入:nums = [3,3], target = 6
輸出:[0,1]
原因分析:
想法一:使用倆次循環遍歷。但是時間復雜度太高O(n^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(nums[i]+nums[j]==target)return new int[]{i,j};}}}
}
class Solution {public int[] twoSum(int[] nums, int target) {// 外層循環遍歷每個元素(除了最后一個)for (int i = 0; i < nums.length - 1; i++) {// 內層循環遍歷當前元素之后的所有元素for (int j = i + 1; j < nums.length; j++) {// 檢查兩數之和是否等于目標值if (nums[i] + nums[j] == target) {// 找到解,立即返回索引對return new int[]{i, j};}}}// 理論上不會執行到這里(題目保證有解)return new int[0]; // 保證編譯通過}
}
解決方案:
遇到判斷這個元素是否在集合里出現過的時候(哈希表法):里面有倆種結構(數組與Set)做哈希映射
import java.util.HashMap;
class Solution {public int[] twoSum(int[] nums, int target) {// 創建哈希表:鍵=數組元素值(Integer), 值=元素索引(Integer)HashMap<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);} // 無解時返回空數組(實際不會執行)return new int[0]; // 創建新的空數組對象}
}
二、Set 與 Map 的關系與區別
1. Map(映射):鍵值對集合
核心特征:
- 存儲鍵值對(Key-Value pairs)
- 鍵唯一,值可重復
- 通過鍵快速檢索值
// Java HashMap 示例
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1); // 插入鍵值對
int count = map.get("apple"); // 通過鍵獲取值
2. Set(集合):唯一元素容器
核心特征:
- 存儲不重復的元素
- 本質是鍵的集合(值被忽略)
- 基于 Map 實現(值用固定占位對象)
// Java HashSet 源碼(簡化版)
public class HashSet<E> {private transient HashMap<E, Object> map;private static final Object PRESENT = new Object(); public boolean add(E e) {return map.put(e, PRESENT) == null; // 值固定}
}
使用選擇建議
- 需存儲關聯數據 → Map
// 用戶ID到名字的映射 Map<Integer, String> userNames = new HashMap<>();
- 只需檢查元素存在性 → Set
// 黑名單ID檢查 Set<Integer> blacklist = new HashSet<>();
三、自動拆箱與裝箱
由包裝類轉成基本類型(如integer與int)在java5之后可以自動轉換。Java 集合框架(如 HashMap)只能存儲對象,所以使用包裝類。
使用包裝類好處:
1.可以為null值
2.有額外的擴展方法
四、為什么要使用泛型
泛型 <K,V> 指定鍵值對的類型 保證類型安全,避免類型轉換
五、為什么要返回一個數組前要加new
new = 拿新盒子:創建數組就像拿新盒子裝東西,空盒子也需要拿(new)