leetcode: 3Sum

news2024/11/17 12:32:59

leetcode: 3Sum

  • 1. 题目描述
  • 2. 思考
  • 3. 解题
  • 3. 总结

1. 题目描述

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] 
such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.

Example1

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
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.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.

Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.

Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.

Constraints:

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

2. 思考

  在做该题之前,建议对Two Sum和leetcode: Two Sum II - Input Array is Sorted,这两道题目先进行了解。
  Two Sum问题的最优时间复杂度为 o ( n ) o(n) o(n),因此对于3Sum问题应该来讲较容易的写出时间复杂度为 o ( n 2 ) o(n^2) o(n2)的解法。但该题目的难点在于triplet要找出所有的方案,同时要去重。
  首先,由于当前预设的时间复杂度为 o ( n 2 ) o(n^2) o(n2),因此可以先对array进行排序,这样不会改变时间复杂度的量级,同时有利于下面的去重操作。
  首先对于外层循环,我们仅对首次遇到的元素进行进一步的内层循环。如何理解这句话:
在这里插入图片描述
  假如当前外层循环,进行到红色区域段。对于第一个-7, 可以将其之后的数组 S S S进行内层循环,找出和为7的两个元素的所有不重复方案。找到的方案熟练假设为 n n n
  假设想对非首次遇到的元素进行进一步的内层循环,假设找到的方案假设为 n ′ n^{'} n,此时是不可以的,会导致最终重复的解决方案。
在这里插入图片描述
  因为 S ′ ⊂ S S^{'}\subset S SS,而两者的目标都是一致:寻找到和为7的元素。必然会导致 n ′ ⊂ n n^{'} \subset n nn。也即方案的重复,因此对于外层循环,我们仅对首次遇到的元素进行进一步的内层循环。
  对于内层循环,与之类似,也是通过跳过重复的元素来,防止方案重复。

3. 解题

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;

        for(int i = 0; i < nums.size(); ++i){
            if(0 == i || nums[i - 1] != nums[i]){
                twoSum(nums, i, res);
            }
        }
        return res;
    }
private:
    void twoSum(vector<int>& nums, int i, vector<vector<int>> &res){
        int left = i + 1, right = nums.size() - 1;
        while(left < right){
            int sum = nums[i] + nums[left] + nums[right];
            if(sum < 0){
                ++left;
            }
            else if (sum > 0){
                --right;
            }
            else{
                res.push_back({nums[i], nums[left++], nums[right--]});
                while(left < right && nums[left - 1] == nums[left])
                    ++left;
            }
        } 
    }
};

  其中,保证了,若以nums[i]为开始(3元素方案),则后续的方案不会重复。

 if(0 == i || nums[i - 1] != nums[i]){
            twoSum(nums, i, res);

  该段代码,保证了若以nums[left]为开始(2元素方案),则后续的方案不会重复。

        while(left < right && nums[left - 1] == nums[left])
            ++left;

3. 总结

  该题相对较难,尤其是消除重复方案这部分,最好以类似于动态规划的思想(假设子问题已解决)来理解。在一定理解的基础上进行记忆。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫Python入门好学吗?学什么?

爬虫Python入门好学吗&#xff1f;学爬虫需要具备一定的基础&#xff0c;有编程基础学Python爬虫更容易学。但要多看多练&#xff0c;有自己的逻辑想法。用Python达到自己的学习目的才算有价值。如果是入门学习了解&#xff0c;开始学习不难&#xff0c;但深入学习有难度&#…

2022年12月电子学会Python等级考试试卷(一级)答案解析

青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;一级&#xff09; 一、单选题(共25题&#xff0c;共50分) 1. 关于Python语言的注释&#xff0c;以下选项中描述错误的是&#xff1f;&#xff08; &#xff09; A. Python语言有两种注释方式&…

JavaEE16-Spring事务和事务传播机制

目录 1.为什么需要事务&#xff1f; 2.MySQL中事务的使用 3.Spring中事务的实现 3.1.编程式事务&#xff08;手动写代码操作事务&#xff09; 3.2.声明式事务&#xff08;利用注解自动开启和提交事务&#xff09;(使用为主) 3.2.1.Transactional作用范围 3.2.2.Transact…

JetpackCompose从入门到实战学习笔记8—ConstraintLayout的简单使用

JetpackCompose从入门到实战学习笔记8—ConstraintLayout的简单使用 1.简介&#xff1a; Compose 中的 ConstraintLayout ConstraintLayout 是一种布局&#xff0c;让您可以相对于屏幕上的其他可组合项来放置可组合项。它是一种实用的替代方案&#xff0c;可代替使用多个已嵌…

JVM垃圾回收机制GC理解

目录JVM垃圾回收分代收集如何识别垃圾引用计数法可达性分析法引用关系四种类型&#xff1a; 强、软、弱、虚强引用软引用 SoftReference弱引用 WeakReferenceWeakHashMap软引用与虚引用的使用场景虚引用与引用队列引用队列虚引用 PhantomReference垃圾回收算法引用计数复制 Cop…

06- 梯度下降(SGDRegressor) (机器学习)

梯度下降算法也是先构建误差值的函数, 通过求误差值函数的最小值来达到误差最小的目的, 不过梯度下降是先随机取值, 然后求函数在该点的导数, 如果导数为正, 下一次取值向反方向移动, 如果导数为负, 正向移动, 直到导数取值极小时, 认定误差达到一个可以接受的范围, 然后导出相…

解读手机拍照的各个参数(拍照时,上面会有6个符号)

1第一个符号是闪光灯符号&#xff0c;如下图所示。有四种模式&#xff0c; 手机的闪光灯分别为关闭、自动、开启和常亮四种状态。 关闭&#xff1a;就是在任何情况下都不会闪光 自动&#xff1a;由手机来判断此时的光线强弱&#xff0c;若手机测光认为光线太弱&#xff0c;则…

前端限制 git commit 提交格式

团队开发中&#xff0c;每个人 git commit 的习惯都不一样&#xff0c;这样不利于对更新日志的筛选&#xff0c;也可以防止同事跑路后&#xff0c;出现 bug 后&#xff0c;看不懂他当时提交的日志究竟是改了个 bug 还是新增了一个功能&#xff0c;影响开发效率。 这时候就需要…

springboot驾校报名系统 微信小程序

系统分为用户和管理员&#xff0c;驾校教练三个角色 用户微信小程序端的主要功能有&#xff1a; 1.用户注册和登陆系统 2.用户查看驾校教练信息 3.用户查看驾校信息 4.用户查看驾校的车辆信息 5.用户查看驾校考试信息&#xff0c;在线报名考试 6.用户可以在线预约驾校的教练 7.…

深度学习笔记--修改、增加和删除预训练模型的特定层

目录 1--前言 2--初始化 VGG16 模型 3--修改特定层 4--新增特定层 5--删除特定层 6--固定预训练模型的权重 7--综合应用 1--前言 基于 Pytorch&#xff0c;以 VGG16 模型为例&#xff1b; 2--初始化 VGG16 模型 from torchvision import models# 初始化模型 vgg16 mo…

Java 反射详解

一、反射 1、什么是反射 反射允许对成员变量、成员方法和构造器的信息进行编程访问。 补充:暴力反射,非public修饰需要打开权限 setAccessible(boolean) 2、反射的作用 利用反射创建的对象可以无视修饰符调用类里面的内容可以跟配置文件结合起来使用&#xff0c;把要创建的对象…

【Jest】Jest单元测试环境搭建

文章目录前言1、项目环境搭建初始化仓库安装ts环境安装jest环境2、初始化项目文件夹前言 今天开始&#xff01;&#xff01;&#xff01;学习vue源码&#xff0c;那么要学习源码前首先要了解Jest。 https://www.jestjs.cn/ 官网自带中文非常友好&#xff01; 1、项目环境搭建…

【C++面试问答】搞清楚深拷贝与浅拷贝的区别

问题 深拷贝和浅拷贝的区别是面试中的常见问题之一&#xff0c;对于不同的编程语言&#xff0c;这个问题的回答可能稍有差别&#xff0c;下面我们就来探索一下它们之间的异同吧。 先来看看在JavaScript对象的深拷贝与浅拷贝的区别&#xff1a; 浅拷贝&#xff1a;只是复制了…

Postgresql 根据单列或几列分组去重row_number() over() partition by

Postgresql 根据单列或几列分组去重row_number() over() partition by 一般用于单列或者几列需要去重后进行计算值的 count(distinct(eid)) 可以 比如有个例子&#xff0c;需要根据名称&#xff0c;城市去筛选覆盖的道路长度&#xff0c;以月因为建立了唯一索引是ok的&#…

前端项目集成Vite配置一览无余

Vite配置文件 默认指定&#xff1a;vite.config.js。自定义指定&#xff1a;vite --config 自定义名称.js。 Vite相关命令 查看Vite有哪些命令&#xff1a;npx vite -help。 --host [host]// 指定域名 --port <port>// 指定端口 --https // 使用 TLSHTTP/2 --cors //…

Spring 中 ApplicationContext 和 BeanFactory 的区别

文章目录类图包目录不同国际化强大的事件机制&#xff08;Event&#xff09;底层资源的访问延迟加载常用容器类图 包目录不同 spring-beans.jar 中 org.springframework.beans.factory.BeanFactoryspring-context.jar 中 org.springframework.context.ApplicationContext 国际…

HTTP 和 HTTPS 的区别

文章目录前言一、HTTP 与 HTTPS 的基本概念HTTPHTTPS二、HTTP 和 HTTPS协议的区别前言 浏览网站时&#xff0c;我们会发现网址有两种格式&#xff0c;一种以http://开头&#xff0c;一种https://开头。好像这两种格式差别不大&#xff0c;只多了一个s&#xff0c;实际上他们有…

Java零基础教程——数组

目录数组静态初始化数组数组的访问数组的动态初始化元素默认值规则&#xff1a;数组的遍历数组遍历-求和冒泡排序数组的逆序交换数组 数组就是用来存储一批同种类型数据的容器。 20, 10, 80, 60, 90 int[] arr {20, 10, 80, 60, 90}; //位置 0 1 2 3 4数组的…

死锁的原因及解决方法

❣️关注专栏&#xff1a; JavaEE 死锁☘️1.什么是死锁☘️2.死锁的三个典型情况☘️2.1情况一☘️2.2情况二☘️2.2.1死锁的代码展示☘️2.3多个线程多把锁☘️3死锁产生的必要条件☘️3.1互斥性☘️3.2不可抢占☘️3.3请求和保持☘️3.4循环等待☘️4如何避免死锁☘️4.1避免…

【Spark分布式内存计算框架——Spark Core】6. RDD 持久化

3.6 RDD 持久化 在实际开发中某些RDD的计算或转换可能会比较耗费时间&#xff0c;如果这些RDD后续还会频繁的被使用到&#xff0c;那么可以将这些RDD进行持久化/缓存&#xff0c;这样下次再使用到的时候就不用再重新计算了&#xff0c;提高了程序运行的效率。 缓存函数 可以…