LeetCode 热题 100——两数之和

169 阅读3分钟

001.jpg 首先,最简单的方法是暴力法,就是遍历每个元素,然后对于每个元素,再遍历剩下的元素,看看有没有满足条件的。这样的话,时间复杂度是O(n²),对于数组很大的情况,比如n是10^4的话,这样的复杂度可能会超时。不过题目里给的进阶要求是希望时间复杂度小于O(n²),所以应该需要更高效的方法。

那有没有更好的方法呢?记得之前学过哈希表的方法,可以用空间换时间。具体来说,我们可以用一个哈希表来存储已经遍历过的元素的值和它们的下标。然后,对于当前元素nums[i],我们检查哈希表中是否存在target - nums[i]这个值。如果存在,那么说明之前已经有一个元素和当前元素的和等于target,这时候直接返回它们的下标就可以了。这样的话,只需要一次遍历,时间复杂度是O(n),空间复杂度也是O(n),因为哈希表存储了最多n个元素。

那这样的话,具体的步骤应该是这样的:

  1. 初始化一个空的哈希表,用来存储元素值和对应的下标。

  2. 遍历数组中的每一个元素nums[i]:

    a. 计算差值complement = target - nums[i]。

    b. 检查这个complement是否存在于哈希表中:

  • 如果存在,则返回当前索引i和哈希表中存储的complement对应的索引。

  • 如果不存在,则将当前元素nums[i]作为键,下标i作为值存入哈希表中。

  1. 由于题目保证有且只有一个答案,所以循环中一定能找到解,不需要处理无解的情况。

举个例子,比如示例1中的nums = [2,7,11,15], target=9。遍历到第一个元素2的时候,计算complement是7,此时哈希表为空,没有找到,所以将2存入哈希表。接着遍历到7,计算complement是9-7=2,这时候哈希表中存在2对应的下标0,所以返回[0,1]。这样就正确了。

如果数组中出现多个结果集,则会先返回第一个。例如:nums=[3,3,3],target=6。当数组遍历到第二个3时(即[3,1]),得到正确结果,代码结束,返回结果值。

代码

import java.util.HashMap;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            // 查询哈希表中是否已存在键为complement的数据
            if (map.containsKey(complement)) {
                // map.get(complement)从哈希表中获取补数对应的索引
                return new int[] { map.get(complement), i };
            }
            // 如果补数不存在,将当前元素的值nums[i]作为键,索引i作为值存入哈希表
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}
class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap();
        
        for(int i = 0,j=nums.length-1; i<=j;){
            int complement = target-nums[i];
            if(map.containsKey(complement)){
                return new int[]{i,map.get(complement)};
            }
            // i++ 先返回i的值,再加加
            map.put(nums[i],i++);
            if(map.containsKey(target-nums[j])){
                return new int[]{j,map.get(target-nums[j])};
            }
            
            map.put(nums[j],j--);
        }
        return new int[]{};
    }
}