两数之和
题目链接:https://leetcode-cn.com/problems/two-sum/
方法一:暴力法
暴力法很简单,两层for循环遍历每个元素,并计算加和。如果加和等于target值且不是同一下标的元素,就找到了目标数组。
时间复杂度:O(n^2)。空间复杂度:O(1)
class Solution { public int[] twoSum(int[] nums, int target) { int firstpos,secondpos; for(int i = 0;i<nums.length;i++){ for(int j = i+1;j<nums.length;j++){ if(i!=j&&nums[i]+nums[j]==target){ return new int[]{i,j}; } } } throw new IllegalArgumentException("No two sum solution"); } }
方法二:为了对时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找到它的索引。
为了保持数组中的每个元素与其索引相互对应,可以利用哈希表。
通过以空间换取速度的方式,我们可以将查找时间从O(n)降低到O(1)。哈希表正是为此目的而创建的,它支持以近似恒定的时间进行快速查找。
一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到哈希表中。然后,在第二次迭代中,我们检查每个
元素所对应的目标元素(target - nums[i])是否存在于哈希表中。注意,该目标元素不能是nums[i]本身.
class Solution { public int[] twoSum(int[] nums, int target) { Map<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"); } }
时间复杂度:O(n)
将包含有n个元素的数组遍历了两次。由于哈希表将查找时间缩短到O(1),所以总的时间复杂度为O(1)。
空间复杂度:O(n)
所需的额外空间取决于哈希表中存储的元素数量,该表中存储了n个元素。
对于方法二我们还可以进行优化---在将元素插入表的同时,我们还可以回头检查表中是否已经存在目标值。
方法三:
事实证明,我们可以一次完成。在进行迭代并将元素插入到哈希表的过程中,我们还会回头来检查表中是否已经存在当前元素所对应的元素。如果它存在,那么我们就找到了相应的解,并立即将其返回。
class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer,Integer> map = new HashMap<>(); int complement = 0; for (int i = 0; i < nums.length; i++) { complement = target - nums[i]; if(map.containsKey(complement)){ return new int[]{map.get(complement),i}; } } throw new IllegalArgumentException("No two sum solution"); } }