题目:两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。
示例
var nums = [2,7,11,15], target = 9;
方法一:暴力法
解题思路
通过两层循环穷举所有可能的数字组合,逐一检查它们的和是否等于目标值。
外层循环固定左手元素,想象你左手依次抓住数组中的每个数字(先抓第一个数2,再抓第二个数7...);内层循环寻找匹配元素,右手从左手抓取元素的后一位开始向右尝试所有数字;检查当前左右手数字之和是否等于target
,一旦找到符合条件的组合,立即返回索引并终止函数。
代码实现
var twoSum = function(nums, target) {
// 外层循环,从第一个元素开始遍历
for(let i = 0; i < nums.length; i++) {
let left = nums[i]; // 左手握着当前元素(比如第一个元素2)
// 内层循环,从外层循环当前元素的下一个元素开始遍历
for(let j = i + 1; j < nums.length; j++) {
let right = nums[j]; // 右手握着后面的元素
// 检查两手握的数的和是否等于目标值
if(left + right == target) {
return [i, j]; // 如果等于,返回两个索引
}
}
}
};
console.log(twoSum(nums, target));
复杂度分析
- 时间复杂度为 O(n²) ,其中n是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
外层循环 内层查找
O(n) × O(n) = O(n²)
- 空间复杂度为 O(1) ,仅用常数级变量
i
、j
、left
、right
,无额外数据结构。
方法二:数组中的 indexOf 方法
解题思路
通过计算补数来优化两数之和问题,但本质上仍属于顺序查找策略。
对于当前元素 nums[i]
,能与之配对的和等于 target
的元素必然是 target - nums[i]
,即补数。通过 indexOf
方法在数组中线性搜索补数,注意避免同一元素被使用两次。
代码实现
var twoSum = function(nums, target) {
for (let i = 0; i < nums.length; i++) {
// 计算当前元素所需的补数(即目标值减去当前元素)
let item = target - nums[i];
// 在数组中查找这个补数是否存在
let j = nums.indexOf(item);
// 检查补数是否存在且不是当前元素本身(避免重复使用同一个元素)
if (j !== -1 && j !== i) {
return [i, j]; // 返回两个索引
}
}
};
复杂度分析
- 时间复杂度为 O(n²) ,虽然代码看似单层循环,但
indexOf
的内部遍历使其时间复杂度仍为 O(n²),与暴力双循环相同。 - 空间复杂度为 O(1) ,仅使用常数级变量。
方法三:哈希表法
解题思路
利用哈希表实现补数查找,空间换时间策略。
创建空对象作为哈希表,用于存储已遍历元素的值与其索引位置的映射关系,通过键名item
检查补数是否已存在哈希表中,当补数存在于哈希表,说明之前已遍历过该元素,直接返回两者索引;若未找到补数,将当前元素存入哈希表,供后续元素查找。后出现的重复元素会覆盖前值。
代码实现
var twoSum = function(nums, target) {
let diff = {}; // 创建一个空对象来存储数字和它们的索引
for(var i = 0; i < nums.length; i++) {
let item = target - nums[i]; // 计算当前数字与目标的差值
// 检查这个差值是否在diff对象中存在
if(diff[item] !== undefined) {
return [diff[item], i]; // 如果存在,返回两个索引
}
// 如果不存在,将当前数字和它的索引存入diff对象
diff[nums[i]] = i;
}
};
执行示例
步骤 | i | nums[1] | 补数(item) | diff内容 | 操作 |
---|---|---|---|---|---|
1 | 0 | 2 | 7 | {} | 存入 diff[2]=0 |
2 | 1 | 7 | 2 | {2:0} | 发现diff[2]存在 → 返回[0,1] |
复杂度分析
- 时间复杂度为 O(n) ,仅需一次遍历,n为数组长度。
- 空间复杂度为 O(n) ,最坏情况需存储所有元素。