题解是官方的,本文主要写个人的一些理解,希望对大家有帮助
题目如下:
1.暴力枚举解决
看到这个题的第一反应就是暴力,穷举出所有的两个数的组合,判断是否和为target,如果是则返回。代码如下:
public static int[] twoSum1(int[] nums, int target) {
//先匹配nums[0]和nums[1],不行就nums[0]和nums[2]...
//如果nums[0]和其他元素都匹配失败,再从nums[1]和nums[2]开始匹配...
for (int i = 0; i < nums.length - 1; i++) {
int num1 = nums[i];//第一个数
for (int j = i + 1; j < nums.length; j++) {
int num2 = nums[j];//第二个数
if (num1 + num2 == target){
return new int[]{i,j};
}
}
}
//如果没找到则返回null
return null;
}
2.hashmap解决
有没有时间复杂度更小的方法?是有的,就是利用hashmap
代码如下:
public static int[] twoSum2(int[] nums, int target) {
//创建hashMap,key保存数组元素的值,value保存元素对应的索引
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (hashMap.containsKey(target-nums[i])){
//target-nums[i]是希望当前元素nums[i]能匹配到的元素值,如果在hashmap中存在,就直接返回索引
return new int[]{ hashMap.get(target-nums[i]), i};
}
//如果在hashmap中没找到,就将当前元素存入hashmap然后遍历下一个
hashMap.put(nums[i],i);
}
//如果最后一个都没遍历到,返回null
return null;
}
/** *
思路是,枚举数组中的每一个数 x,寻找数组中是否存在 target - x。
上面的暴力枚举方法时间复杂度较高的原因是,枚举到x时,寻找 target - x 的时间复杂度过高,需要遍历一遍数组查找target-x
而使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
做法是让hashmap记录遍历过的元素。
每遍历到一个元素,就到哈希表中寻找是否有之前的元素和当前元素匹配 。
使用containsKey
如果有匹配的元素,直接返回;
如果没有,则将当前元素的值和索引记录到hashmap中,以元素的值为Key,索引为value。然后遍历下一个元素,重复。
此种方法相当于遍历到arr[1]时让arr[1]匹配hashmap中已有元素arr[0],不匹配就跳过,再把(arr[1],1)加到hashmap中。
你可能有疑问,那arr[1]不是只匹配了arr[0]吗,不是应该arr[1]和其他所有元素都匹配一次吗?但是,这里如果arr[1]匹配arr[0]失败,那么arr[2]又会匹配arr[1]和arr[0],如果又失败,arr[3]也会匹配arr[0],arr[1],arr[2]这些已经被添加到hashmap中的元素,以此类推。所以arr[1]是可以和所有元素都匹配一次的,其他元素亦然。
*/
3.思考:为什么要用containsKey而不用containsValue?
我们存储元素值和索引到hashmap时,以元素值作为entry的key,以索引作为entry的value,好像和我们的习惯违背,一般首先想到的不都是索引作为key吗?
的确如此。但这里还是要采用这样的存储方法,然后使用containsKey。因为,如果把元素值作为value,那么判断containsValue为真后,怎么根据value拿到key?要知道key是唯一的但value不是,一个value值可能对应多个key,所以是无法拿到的。
以上只是一点个人的思考,如有谬误欢迎大家指正!