LeetCode两数之和(Two Sum)JS短代码运行逻辑详解
三行两数之和解法原理详解
逐行代码拆解
- 第一行
var twoSum = function(nums, target) {是常规的函数声明,和你写的箭头函数实现的作用完全一致,只是语法写法不同。 - 第二行
for(let [k,v] of nums.entries()){用到了数组的entries()方法,遍历数组时会逐次返回[当前元素下标, 当前元素值]的结构,所以这里的k就对应你暴力解法里的外层循环变量i,v对应nums[i]。 - 第三行是核心判断逻辑,我们拆分理解:
- 首先计算目标差值
target - v:也就是要找的、能和当前值v相加刚好等于target的数值,和你暴力解法里nums[i] + nums[j] === target的判断逻辑等价,只是换了个写法变成找nums[j] === target - nums[i]。 - 判断条件
nums.slice(k+1).lastIndexOf(target-v) > -1:
nums.slice(k+1)是把原数组从当前下标k的后一位开始切割,得到一个只包含k之后所有元素的新数组,作用是保证不会重复使用当前元素或者之前已经遍历过的元素,对应你暴力解法里j = i + 1的逻辑,避免重复校验。lastIndexOf(target-v)会从后往前查找目标差值在切割后的新数组里的下标,找不到就返回-1,只要返回值大于-1就说明k之后的位置存在我们要找的数值。
- 满足条件后返回
[k, nums.lastIndexOf(target-v)]:直接在原数组调用lastIndexOf拿到目标差值在原数组的下标,和当前下标k组合就是最终结果。
- 首先计算目标差值
示例运行验证
拿示例3的输入nums = [3,3], target = 6跑一遍逻辑:
- 第一次遍历:k=0,v=3,目标差值为6-3=3
- 切割数组得到
[3],在这个数组里找3的lastIndexOf结果为0,大于-1,满足条件 - 原数组找3的
lastIndexOf结果为1,返回[0,1],符合预期。
补充:遇到重复值的场景下
lastIndexOf会返回最后一个匹配的下标,刚好就是k之后的目标元素下标,不会取到当前k位置的元素,逻辑不会出错。
额外说明
这个写法只是语法上更简洁,本质还是暴力解法的变种:slice和lastIndexOf都是O(n)时间复杂度的操作,套在循环里整体时间复杂度还是O(n²),和你写的双层循环性能没有差异。如果要追求更高性能,还是要使用哈希表存储已遍历元素的O(n)解法。
内容的提问来源于stack exchange,提问作者MiniDracaena
相关产品推荐
相关产品推荐

