当前位置: 首页 > article >正文

【LeetCode热题100】【双指针】三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入: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] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

题解

前有两数之和用哈希在O(n)的时间复杂度内解决,现有三数之和需要用到双指针在O(n²)内解决

暴力的话需要三层循环而且需要去重复

我们可以先从小到大排序一下元素,那么现在元素是有序的了,而且左边的比右边的小或者相等

如果某元素大于0了,那么这个元素后面是不会有答案出现了,因为后面的元素不会比前面的小

找到一个小于等于0的元素了,让左指针指向后面一个元素,右指针指向最大的元素,把他们相加起来,如果和等于0,那么这三个是一个答案存起来,继续看左边的元素往右有没有相同的元素,如果有的话更新一下左边指针,因为这三个数字的组合已经是答案了,相同的就是重复了,然后同样看右边的元素往左有没有相同的元素,有的话也更新一下

如果和不等于0,和比0小,那么移动左指针让候选元素变大,如果和比0大,那么移动右指针让候选元素变小

排序nlogn,遍历元素n,两层while循环因为循环条件都是一起的加起来也是n,所以就是n²

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if(nums.size()<3)
            return {};
        sort(nums.begin(),nums.end());
        if(nums[0]>0) // 如果最小的都大于0了那么肯定没有
            return {};
        vector<vector<int>>answer;
        for(int i=0;i<nums.size();i++){
            if(i>0&&nums[i]==nums[i-1])  // 元素相同的不做判断
                continue;
            int left=i+1,right=nums.size()-1;  // 取左右双指针
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(sum==0){
                    answer.push_back({nums[i],nums[left],nums[right]});
                    while(left<right&&nums[left]==nums[left+1]){left++;}  // 左边相同的去掉
                    while(left<right&&nums[right-1]==nums[right]){right--;}  // 右边相同的去掉
                    left++;
                    right--;
                }else if(sum<0){  // 和不为0但是小于0说明和太小了移动左指针变大
                    left++;
                } else{  // 移动右指针变小
                    right--;
                }
            }
        }
        return answer;
    }
};


http://www.kler.cn/a/161503.html

相关文章:

  • java模拟键盘实现selenium上下左右键 table中的左右滚动条实现滚动
  • android dvr黑屏
  • IEC60870-5-104 协议源码架构详细分析
  • Camera Tuning中AE/AWB/AF基础知识介绍
  • 3DTiles之i3dm介绍
  • 给查询业务添加redis缓存和缓存更新策略
  • java中synchronized和Lock的区别是什么?
  • 免费文章生成器的种类,3款免费的文章生成器推荐
  • 计算机网络的分类
  • 跨境电商独立站怎么获取流量 跨境电商引流的两个方法
  • 实例分割 Mask-RCNN
  • docker数据卷
  • 熟悉ElasticSearch 集群中搜索数据的过程吗?
  • Pytorch在二进制层面比较张量中的各行是否相同,并返回不相同的各行
  • 【面试常考150题】1、88合并两个有序数组
  • MySQL核心知识点整理大全1-笔记
  • Mybatis 详解
  • SSM项目实战-登录验证成功并路由到首页面,Vue3+Vite+Axios+Element-Plus技术
  • 【尘缘送书第五期】Java程序员:学习与使用多线程
  • 搜维尔科技:Varjo XR-4 系列-专为极致沉浸感而打造!
  • 【二叉树】
  • GORM 自定义数据类型-枚举 (今天仓促,明天修改)
  • 总结1077
  • Flask+vue+axios完成导出Excel表格的功能
  • HTTP不同场景下的通信过程和用户上网认证过程分析
  • labelme等标注工具/数据增强工具输出JSON文件格式检查脚本