两数之和你会,三数之和你也会吗?o_O

前言

多少人梦想开始的地方,两数之和。

但是今天要聊的不是入门第一题,也没有面试官会考这一题吧....不会真有吧?

咳咳不管有没有,今天的猪脚是它的兄弟,三数之和,作为双指针经典题目之一,也是常常作为面试常考题出现。今天就来和大家分析分析这题的详细解法和双指针题目的思路。

三数之和

题目链接:15. 三数之和

示例 1:

scss 复制代码
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

初始代码:

ini 复制代码
var threeSum = function(nums) {
};

解题思路

看完了题目,这题的重点是:

  1. 数组是无序的
  2. 不能有重复的答案
  3. 每个答案数组都需要进行记录,同时i!=j,j!=k,

那么先开始思考:

  • 暴力是否可以得出答案,答案是可以的。好下课- ̗̀(๑ᵔ⌔ᵔ๑)!,咳咳但是由于暴力时间复杂度为O(n)^3所以铁定是超时的
  • 那么接下就是是否能进行优化,暴力是会具有大量的重复查询,我们需要做的是消除重复查询 并且缩短查询时间
  • 消除重复查询的办法,我选择的是对数组先进行排序。这样相同的元素放在一起,可以防止重复查询。
  • 缩短查询时间,我选择的是双指针,既然是双指针,那么必须需要固定好一个数,才能让双指针进行移动。这里我选择的是固定第一个数字,第二个数字为左指针指向第一个数字后的一位数,第三个数字为右指针指向数组末尾的数。下面是例图:

因为数组是已经排好了序,所以我们只需要把这题当作一下问题求解即可:
当给你一个数target,让你在一个有序数组中找到两个数和为(-target)的所有解,并且解不能相同。是不是感觉特别简单。从三个数的寻找直接变成了两个数求和 ,那么接下来就来开始做题。

做题步骤

下面是伪代码,大家可以看着能不能写出来♡⸜(˶˃ ᵕ ˂˶)⸝♡

javascript 复制代码
var threeSum = function(nums) {
//1- 首先定义一个返回的结果数组,result

//2- 对数组进行排序

//3- 排好序之和就进行数组遍历
//数组遍历从下标0开始,先遍历第一个数的范围(arr.length-3),因为三数之和必须需要三个数
// 所以第一个数的下标范围为 0-length-3

//4- 第一个数被固定后,需要进行双指针遍历剩余的数,但是在遍历之前我们需要进行去除
//重复元素的操作,就是判断第一个数为target时候是否已经查询过结果,如果查询过就直接跳过

//5-去重之后,就定义双指针一个指向第一个数之后,一个指向数组末尾,定义一个数记录三数之和,方便我
//们移动双指针

//6-我们这里需要循环判断,压缩数组的空间,来找到所有符合的答案,所以这里我们需要while循环
//直到条件为左指针>=右指针下标时结束寻找

//7-如果答案符合我们需要进行记录,并且,第二个数和第三个数也需要进行去除重复元素的操作

//8- 结束循环返回result数组
};

正式代码:

scss 复制代码
var threeSum = function(nums) {
//1- 首先定义一个返回的结果数组,result

    const result = [];
    
//2- 对数组进行排序

    nums.sort((a,b)=>a-b);
    
//3- 排好序之和就进行数组遍历
//数组遍历从下标0开始,先遍历第一个数的范围(arr.length-3),因为三数之和必须需要三个数
//所以第一个数的下标范围为 0-length-3

    for(let i=0,len=nums.length;i<=len-3;i++){
    
//4- 第一个数被固定后,需要进行双指针遍历剩余的数,但是在遍历之前我们需要进行去除
//重复元素的操作,就是判断第一个数为target时候是否已经查询过结果,如果查询过就直接跳过,如果第一
//数大于0,那么也无需进行遍历直接返回即可因为数组是排好序的。第一个数都大于0,那么三数之和不可能为0

    if(nums[i]>0)return result;
    if(i!=0&&nums[i]==nums[i-1]){continue;}

//5-去重之后,就定义双指针一个指向第一个数之后,一个指向数组末尾,定义一个数记录三数之和,方便我
//们移动双指针

    let sum =0;let left = i+1;let right = len-1;

//6-我们这里需要循环判断,压缩数组的空间,来找到所有符合的答案,所以这里我们需要while循环
//直到条件为左指针>=右指针下标时结束寻找

    while(left<right){
    sum =nums[i]+nums[left]+nums[right];
    
//7-如果答案符合我们需要进行记录,并且,第二个数和第三个数也需要进行去除重复元素的操作
      
            if(sum==0){
                result.push([nums[i],nums[left],nums[right]])
                while(left<right&&nums[left]==nums[left+1]){
                    left++;
                }
                while(right>left&&nums[right]==nums[right-1]){
                    right--;
                }
                left++;right--;
            }else if(sum>0){right--;}
            else{
                left++;
            }
    }

//8- 结束循环返回result数组
    
    }
 return result;   
}

可以看到效率还是非常不错的,那么本题的分享到此结束。

谢谢大家的观看,喜欢的话可以点个关注或者是点赞,谢谢- ̗̀(๑ᵔ⌔ᵔ๑)。

相关推荐
ggdpzhk8 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
盼海12 分钟前
排序算法(五)--归并排序
数据结构·算法·排序算法
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o5 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app