Leetcode-1. 两数之和

188 阅读2分钟

题目

给定一个整数数组 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(n2) 的算法吗?

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/tw…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  1. 查找表法 使用一个hash表记录遍历过的数值(Key)和其对应的下标(Value),然后遍历数组第i个元素的时候,去hash表中找Keytarget - nums[i]的记录,如果有,则该记录对应Value和当前下标i的两个数字之和为target

该解法是用空间换时间,通过申请数组nums长度的hash表,只需要遍历数组一遍,算法复杂度为O(n)。

查找表法的具体实现有两种:哈希平衡二叉搜索树,由于这里不需要维护顺序性,采用哈希即可。

具体算法

public int[] twoSum(int nums[], int target) {
    int len = nums.length;
    // 初始化的时候尽量在构造中写容量,避免扩容带来的效率问题
    // 用于记录遍历过的数值(key)和下标(value)
    Map<Integer, Integer> hash = new HashMap<>(len - 1);
    // 因为第0个数在空表中一定不会找到对应下标,直接将其放入
    hash.put(nums[0], 0);

    // 循环从nums第二个数字开始
    for (int i = 1; i < len; i++) {
        // 如果hash表中有对应的key就找到和为target的两个数
        if (hash.containsKey(target - nums[i])) {
            return new int[]{i, hash.get(target - nums[i])};
        } else {
            // 否则就将当前遍历的数值作为key下标作为value存入hash中
            hash.put(nums[i], i);
        }
    }
    // 如果程序执行到这里说明该数组中没有两数和为target,抛出异常
    throw new IllegalArgumentException("No Two Sum Solution");
}