给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] —— 原文摘自:力扣(LeetCode) | https://leetcode-cn.com/problems/two-sum读完题目描述,第一感觉是并不难,但出于谨慎(毕竟刚决定来刷题,而且还是第一题😁),还是将题目中提到的重点记了下来:
找出两个整数,但返回的是数组下标每种输入只会对应一个答案数组中同一个元素不能使用两边说实话,第一个想到的方法就是 for 循环搞定,然后,上来就开始写循环。但是,😂,刚写下 for 就又被我删了,js 流处理写多了,第一时间想到的是流处理是不是方便点,但是,准备写的时候又再次卡住了,好久没写 Java ,忘了 Stream 和 Array 怎么转换了! Fuck!!!😂 于是,老老实实用 for 循环实现。(第一次写还写错了,下意识以为给出的案例就是所有测试用例了,写成单重循环了😂!下面的解法是经过整理,重新写的!)
class Solution { public int[] twoSum(int[] nums, int target) { for(int i=0; i < nums.length - 1; i++) { for(int j = i + 1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[] {i, j}; } } } throw new IllegalArgumentException("No two sum solution"); } }双重循环写完,确实相当暴力!但是,既然是来刷题的,那当然是不能满足于此! 但是,由于好久没写 Java ,也好久没接触过算法的需求,而且才刚开始刷算法,一时间脑子有点懵,什么也没想出来!于是,老老实实地看大佬们的解法!
官方的题解中在第二种解法时提到,
保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。
通过以空间换取速度的方式,我们可以将查找时间从 O(n) 降低到 O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)。
感觉可以记下来,作为以后做同类题目的一个快速策略思考方向,但是,对于其中的一句还是没太明白:
一旦出现冲突,查找用时可能会退化到 O(n)
不过,虽然还有些迷糊,但还是先看解法吧!于是,一番查看,包括其他的大佬的解法,最终自己写了一下:
class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for(int i=0; i < nums.length; i++) { map.put(nums[i], i); } for(int i=0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement) && map.get(complement) != i) { return new int[] {i, map.get(complement)}; } } throw new IllegalArgumentException("No two sum solution"); } }在一些解法中或下面的回复中有出现一些说法,说这种解法会存在冲突的情况,前一个数被后一个相同的数覆盖了,或者说是考虑不到多个答案的情况等。 自己试了下,确实存在这种情况(如下),但是综合来说,这种解法还是写下来。
输入:[5, 2, 5, 2] 目标和: 7 第一遍哈希表后: map ==> {2=3, 5=2} 第二遍哈希表时: ① nums[0] = 5, target - nums[0] = 2, map.get(2) = 3, return [0, 3] 但是,更期望的返回结果应该是 [0, 1]解法二中提到会有 Hash 冲突的情况,那么,我们只用一遍哈希表,一遍遍历查找,一遍将把数放进哈希表:
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]; if (map.containsKey(complement)) { return new int[] {map.get(complement), i}; } map.put(nums[i], i); } throw new IllegalArgumentException("No two sum solution"); } }