1.两数之和
1.1我的解法(暴力解法)
思路:将数组遍历,直到遍历到目标为止
public int[] twoSum(int[] nums, int target) {
int []result = new int[2];
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1 ; j < nums.length; j++) {
if (nums[i]+nums[j] == target){
result[0] = i;
result[1] = j;
return result;
}
}
}
return null;
}
1.2听课后的解法(利用哈希)
思路:暴力解法将数组两层循环,时间复杂度为o(n^2),哈希解法将数组元素遍历放入哈希表中,key为值,value为索引,再次遍历数组,用目标值减去当前遍历值,再从哈希表中get,如果能get到且value与当前遍历索引不相等,则解出,时间复杂度为O(n)
public int[] twoSumHash(int[] nums, int target) {
int[] result = new int[2];
HashMap<Integer, Integer> hm = new HashMap<>(nums.length);
//将数组元素放入哈希表
for (int i = 0; i < nums.length; i++) {
hm.put(nums[i], i);
}
//开始遍历数组元素
for (int i = 0; i < nums.length; i++) {
int r = target - nums[i];
Integer i1 = hm.get(r);
if (i1 != null && i1 != i) {
result[0] = i;
result[1] = i1;
return result;
}
}
return result;
}
1.3ds改进方法
1.指出方法2存在关键错误:若数组中存在重复元素(如 [3, 3], target=6),第一次遍历的 hm.put 会覆盖重复元素的索引,导致后续找不到有效解(例如第二个 3 覆盖第一个,后续补数检查时只能找到最后一个索引)。
2.不必要的两次遍历:第一次遍历构建完整哈希表,第二次遍历查找补数。但目标补数可能在未完全构建哈希表时已出现。
最佳方法:单次遍历 + 动态构建哈希表
思路:在遍历数组时进行判断,若target减去当前遍历数能在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 solution");
}
}