目录
问题描述
示例
示例 1
示例 2
示例 3
提示
解决方案
算法思路
过题图片
代码实现
复杂度分析
注意事项
题目链接
结论
问题描述
给定一个整数数组 nums
和一个目标值 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]
提示
2 <= nums.length <= 10^4
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9
- 只会存在一个有效答案
解决方案
算法思路
我们可以使用哈希表(HashMap)来解决这个问题。哈希表的键(Key)是数组中的元素,值(Value)是该元素在数组中的索引。这样,我们可以在遍历数组的同时,检查当前元素的补数(即 target - 当前元素
)是否已经在哈希表中。如果在,我们就找到了一对和为目标值的元素,并返回它们的索引。
排序与双指针
除了使用哈希表,我们还可以使用排序和双指针的方法来解决两数之和问题。这种方法的核心思想是先对数组进行排序,然后使用两个指针(一个指向数组的开始,一个指向数组的末尾)来寻找和为目标值的两个数。
步骤
-
排序:首先,对输入的数组
nums
进行排序。排序后,如果nums[i] + nums[j]
的和小于target
,则i
必须右移,因为所有左侧的元素都比nums[i]
小,无法形成更大的和。如果和大于target
,则j
必须左移,因为所有右侧的元素都比nums[j]
大,无法形成更小的和。 -
双指针查找:初始化两个指针
left
和right
,分别指向数组的起始和结束位置。计算nums[left] + nums[right]
的和,然后根据比较结果移动指针:- 如果和小于
target
,则移动left
指针向右(增加left
的值),因为我们需要一个更大的数来增加总和。 - 如果和大于
target
,则移动right
指针向左(减少right
的值),因为我们需要一个更小的数来减少总和。 - 如果和等于
target
,那么我们找到了一对符合条件的数,返回它们的索引。
- 如果和小于
-
循环直至找到或指针交叉:继续这个过程,直到
left
和right
指针相遇。如果在任何时候left
和right
相遇,这意味着数组中没有两个数的和等于target
,可以返回一个错误标志或空值。
过题图片
代码实现
java
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++) {
map.put(nums[i], i); // 将数值和对应的索引存入HashMap
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i]; // 计算需要找的另一个数
if (map.containsKey(complement) && map.get(complement) != i) { // 如果HashMap中包含这个数,并且不是同一个索引
return new int[]{i, map.get(complement)}; // 返回两个数的索引
}
}
return new int[]{-1, -1}; // 如果没有找到结果,返回一个默认值,例如{-1, -1}。
}
}
复杂度分析
- 时间复杂度:O(n),其中n是数组
nums
的长度。我们只需要遍历一次数组。 - 空间复杂度:O(n),我们需要一个额外的哈希表来存储数组中的元素及其索引。
注意事项
- 确保在哈希表中查找补数时,当前元素的索引与补数的索引不同,以避免使用相同的元素两次。
- 如果数组中有重复的元素,哈希表会帮助我们避免重复计算。
题目链接
1. 两数之和 - 力扣(LeetCode)
结论
通过使用哈希表,我们可以高效地解决两数之和问题。这种方法的时间复杂度和空间复杂度都是线性的,适合处理大规模数据集。