力扣1:两数之和

61 阅读2分钟

1. 两数之和

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");
    }
}