引言:前端时间有一学弟问我LeetCode上这两题如何解,以及思路是怎样来的
🤷♂️:学长,这有两道关于数字之和的题目,你能给我讲解一下吗?
🐱💻:嗯,这两道题目很类似,如果你掌握了思路,那么你肯定也会N数之和的算法
🤷♂️:可是我总找不到他们的相同出发点🤢,到底是怎么样的思路呢
🐱💻:这样吧,我们从最简单的开始,我给你出一道题,两数之和,你试试看能不能做出来
两数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在两个元素 a,b,使得 a + b = 0 ?请你找出所有和为 0 且不重复的二元组。
注意:答案中不可以包含重复的二元组
/*输入:*/ nums = [-1,0,1,2,-1,-4]
/*输出:*/ [[-1,1]]
示例 2:
/*输入:*/ nums = [-6,3,0,2,1,0,-3]
/*输出:*/ [[-3,3],[0,0]]
示例 3:
/*输入:*/ nums = [0]
/*输出:*/ []
🐱💻:第一步你知道应该做什么吗?
🤷♂️:…嗯,我觉得是先把数组排序,这样如果有相同的元素就会集中在一起,我们能清除的知道有多少个
🐱💻:没错,假设经过排序后,我们得到了如下数组,你看出什么来了吗?
[ -3 -1 0 1 2 3 ]
🤷♂️:啊,数组有序之后,我一下就能看出哪两个数组之和为0,分别是-3和3,-1和1
🐱💻:眼睛看当然容易,程序如何写呢?我先用箭头把他们标出来,显然你的任务是先找到-3和3,再找到-1和1
[ -3 -1 0 1 2 3 ]
▲ ▲ ▲ ▲
│ │ │ │
🤷♂️:我想想…,这里是两个数两个数找,好像有点像双指针!一头一尾,判断他们的和是否为0,然后轻松找到-3和3,可以我如何过度到-1和1呢?
[ -3 -1 0 1 2 3 ]
▲ ▲
│ │
🐱💻:双指针的精髓就是你如何选择移动指针,是选择移动左指针还是右指针,我再给你一个例子,你看看你选择移动左指针还是右指针:
[ -5 -4 -2 0 1 4 ]
▲ ▲
│ │
🤷♂️:肯定是移动左指针,然后就找到-4和4了,嘻嘻~
🐱💻:没错,我来告诉你你为什么会选择移动左指针,假设左、右指针指向的数为a和b,因为此时 a + b = -1,小于0,因此我们需要让a或者b其中一个数变大,才有可能让a + b ==0,因为这是一个有序数组,恰好a右边的数字一定大于a,所以选择让左指针向右移动
🤷♂️:(恍然大悟)原来是这样啊,如果a + b == 0的话,那就意味着左右指针都得向中心移动,因为只移动一个指针下一次相加比较肯定不会等于0(数组无重复元素)
🐱💻:你试着写一下程序吧
🤷♂️:
function TwoSum(arr) {
arr.sort((a, b) => a - b)
let res = []
let i = 0
let j = arr.length - 1