指尖的无声告白,算法里的隐约温柔

在这里插入图片描述

公主请阅

  • 1. 三数之和
    • 1. 题目说明
      • 示例 1
      • 示例 2
      • 示例 3
    • 1.2 题目分析
    • 1.3 代码部分
    • 1.3 代码分析
  • 2. 四数之和
    • 2.1 题目说明
      • 示例 1
      • 示例 2
    • 2.2 题目分析
    • 2.3 代码部分
    • 2.4 代码解析

1. 三数之和

在这里插入图片描述
题目传送门


1. 题目说明

给定一个整数数组 nums,判断数组中是否存在三个元素 nums[i], nums[j], nums[k],使得它们的和为 0,返回所有符合条件且不重复的三元组。要求:

  • 三元组 [nums[i], nums[j], nums[k]] 满足 i != j != k,同时 nums[i] + nums[j] + nums[k] == 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]
输出:[]

示例 3

输入:nums = [0, 0, 0]
输出:[[0, 0, 0]]


1.2 题目分析

题目要求nums[i] + nums[j] + nums[k] == 0。那么我们就得在数组中找到这对应的三个数
解法一: 暴力枚举法:将所有的可能性都表示出来,然后利用set进行去重操作
解法二: 使用排序+双指针就能进行解决了
那么对于这两种方法的话我们肯定是选择这个第二种方法的,因为效率高
我来具体讲下我的思路:
我们将排序好的数组的第一个数字进行一个固定的操作,然后从1到n-1这个下标范围进行满足两数之和为0的条件的数字的寻找
然后我们在这个区间之内我们就能利用双指针进行满足条件的数字的寻找了在这里插入图片描述
总结:

  • 1.先排序

  • 2.固定一个数a(我们固定的数小于等于0就行了,不需要去固定大于0的,如果固定的是大于0的数字的话我们是不能在这个数后面的区间之内找到负数的,所以我们固定a的时候我们只需要在负数和0之间进行固定的操作,当a大于0之后我们就不要进行考虑统计了)

  • 3.在该数后面的区间内利用‘双指针算法’,快速找到两个的和等于a就行了

处理细节问题:

  • 1.去重(不借助set进行去重的操作)

    找到一种结果之后,left(right要跳过重复元素)

    当使用完一次双指针算法之后,i也需要跳过重复元素

    避免越界(如果数组中全是0的话,i跳过重复元素,可能会存在越界的情况)

left<right这个就会保证不越界了

  • 2.不漏(将所有情况都找到)

    找到一种结果之后,不要停下来,缩小区间,继续寻找


1.3 代码部分

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums){vector<vector<int>>ret;//用ret来记录我们最终的结果//1.排序sort(nums.begin(),nums.end());//2.利用双指针进行问题的解决int n=nums.size();for(int i=0;i<n;)//固定数a{if(nums[i]>0)//我们固定的数只选择小于0或者等于0的数字,不选择正数,这个是个小优化{break;}//我们在固定数i后面的区间继续双指针的操作的int left=i+1,right=n-1,target=-nums[i];//我们在后面的区间只需要将target寻找到,看看是哪两个指针之和while(left<right){int sum=nums[left]+nums[right];if(sum>target)//说明右边的那个数太大了,我们要往左挪动一位{right--;}else if(sum<target){left++;}else//说明我们已经找到了最终的结果了{ret.push_back({nums[i],nums[left],nums[right]});//将我们最后得到的三元组的答案存放在ret中left++,right--;//这个就是保证没有情况漏掉,进一步缩小区间//去重left和rightwhile(left<right && nums[left]==nums[left-1])//如果下一个数字和前一个数字是相等的话我们一直进行加加的操作,直到我们的这个数和之前的数不相等了{//但是如果我们碰到了特殊情况的话,就是一组数字全是0,然后我们这个Left就是有可能的造成越界的情况了//所以我们在移动的时候我们的left要小于right//所以我们要在这个循环中加上一个条件,就是左指针小于右指针left++;}//处理完left的重复和越界问题之后我们还要处理这个right的重复和越界问题while(left<right && nums[right]==nums[right+1])//nums[right]==nums[right+1]这个就是重复元素//重复的话就进行这个right--的操作{right--;}//通过这两个while循环我们就能实现这个去重的操作了}}//当我们的内部循环第一个while循环结束后我们的第一个i所涉及到的三元组就全部找到了,那么我们接下来就对i进行去重操作i++; while(i<n && nums[i]==nums[i-1]){i++;}//加到nums[i]和前面的数不相同,但是这个也存在越界的情况//我们在这个for循环中我们的第三个条件我们可以不写i++,可以空着,因为我们这里已经存在i++的操作了}return ret;}
};
//时间复杂度是n^2级别的,空间发复杂度logn

1.3 代码分析

我们先用sort进行一个排序的操作

然后通过for循环固定住这个a,并且这个a不能是正数,这个时间个优化,只能是负数和0

我们在固定的那个数的后面那个数开始,直到最后一个数直接的区域通过双指针来获取我们固定的数的相反数,这个相反数就是两个指针之和,

在这里插入图片描述
这个target就是我们固定的那个数字的相反数了

然后我们进行一个while进行循环的操作

对于两数之和的话我们存在三种情况,如果算出来的数大于我们要找的target的值的话,我们就将right–

相反就是left++

还有一种情况就是我们找到了

在这里插入图片描述
在这里插入图片描述
通过这两个代码我们将符合条件的答案存储在这个ret

然后我们进行缩小区域的操作继续进行寻找对应的数字

left++right--进行区域的缩小操作

然后我们最后进行两个指针指向的数字的去重操作
在这里插入图片描述
对于left来说的话就是++后指向的数字和前一个数字是不是相等的

对于right来说的话就是–后的数字是不是和原先的数字是不是相等的话

如果是相等的话分别执行这个left++right--,直到我们找到了这个不重复的数字

但是我们需要在这两个while循环的开头加上一个条件,就是left<right,保证两个指针不越界操作

处理完指针的越界操作之后

我们对i的去重进行一个操作

在这里插入图片描述
我们在for循环中就不需要写i++这个条件了,我们在这里就进行了,直到我们的i不是重复的数字


2. 四数之和

在这里插入图片描述
题目传送门


2.1 题目说明

给你一个由 n 个整数组成的数组 nums,和一个目标值 target。请你找出并返回满足下述全部条件的不重复的四元组 [nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复):

  1. \( 0 <= a, b, c, d < n \)
  2. \( a, b, c, d \) 互不相同
  3. \( nums[a] + nums[b] + nums[c] + nums[d] == target \)

你可以按 任意顺序 返回答案。

示例 1

输入:nums = [1, 0, -1, 0, -2, 2], target = 0
输出:[[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]

示例 2

输入:nums = [2, 2, 2, 2, 2], target = 8
输出:[[2, 2, 2, 2]]


2.2 题目分析

解法一:
排序+暴力枚举+利用set去重
将所有的可能性列出来
解法二:
排序+双指针
我们在这个数组进行元素的固定,从第一个元素开始,然后我们后面的区间利用求三数之和的方法求的目标值

下面讲讲我的思路:

1.依次固定一个数a;

2.在a后面的区间内利用我们在三数之和的思想找到三个数,使这三个数的和等于target-a就行了

在这里插入图片描述

三数之和:

1.依次固定一个数b

2.在b后面的区间内利用双指针找到两个数,使这两个数的和等于target-a-b就行了

细节问题:

1.不重

2.不漏(找到一个结果的时候我们缩小区间继续进行寻找)


2.3 代码部分

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target){vector<vector<int>>ret;//存放结果的数组//1.排序sort(nums.begin(),nums.end());//利用双指针解决问题int n=nums.size();for(int i =0;i<n;)//固定数a{//利用三数之和for(int j=i+1;j<n;)//固定数b{//利用双指针int left=j+1,right=n-1;long long aim=(long long)target-nums[i]-nums[j];//这个就是我们通过双指针要找到的两数之和while(left<right)//{int sum=nums[left]+nums[right];if(sum<aim) left++;else if(sum>aim) right--;else{ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});//固定的a和b以及left和right指向的值//找到一种结果之后我们进行缩小区间的操作继续进行寻找符合条件的数,我们在将结果存放到ret的时候进行left++,right--//去重一:left和right要跳过和之前相同的元素while(left<right && nums[left]==nums[left-1]) left++;//相等的话我们就进行跳过的操作,并且我们保证不越界 while(left<right && nums[right]==nums[right+1]) right--;}}//去重二:现在我们对b进行去重的操作j++;while(j<n && nums[j]==nums[j-1]) j++;//保证不越界并且这个++后的数和之前的数是不相等的,如果相等的话就一直进行++操作,而且我们最上面的for循环中就不需要写j++了,因为我们这里写了}//去重三:i++;while(i<n && nums[i]==nums[i-1]) i++;//同时我们上面的for循环也是不同进行i++的}return ret;}
};

2.4 代码解析

我们先利用vector创建一个数组容器(还没学到,说错了勿喷)
然后我们利用sort进行排序的操作
然后我们计算这个数组的大小
然后我们就可以利用双指针进行后面的操作了
我们利用一个for循环固定住数a
然后在循环里面我们利用我们之前学的三数之和的知识,
我们再使用一个for循环固定住数b,在这个循环里面我们利用双指针找到想要的两数之和
我们先定义leftright
我们在这个循环里面需要找到的两数之和的大小是目标值-a-b的大小
那么这个两数之和就是我们两个指针对应的数据了
我们先创建变量将这个我们需要找的值进行保存,然后我们再通过while循环进行遍历的操作,遍历的条件一定要是left<right,保证不能越界了
我们在循环里面再计算每次的左右指针下标之和sum 然后让sum和我们的目标值aim进行比较,然后再决定移动我们的哪个指针
大于小于的情况不说了,我们就说下等于的情况
当我们找到一种结果之后,我们还要继续往后面进行寻找,但是不能和当次的结果重复了,所以我们要进行去重的操作,我们在去重之前先将这个数据push_backvector容器里面去存着
然后我们就可以开始去重的操作了
还是while循环,这个是对指针进行去重
在这里插入图片描述
然后对我们固定的b进行去重
在这里插入图片描述
然后对a进行去重
在这里插入图片描述
最后将值进行返回就行了
所以我们在这里是有三次去重的操作的
而且都很重要

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿道Intewell操作系统构型介绍之Intewell-C全实时构型

鸿道(Intewell)操作系统主要包括Intewell-C、Intewell-H和Intewell-V三种不同构型产品&#xff1a; Intewell-C Intewell-C是一款工业实时微内核操作系统&#xff0c;由科东软件自主研发&#xff0c;具有超低延迟和最小抖动&#xff0c;保障工业设备可以高效处理时间敏感的现…

python爬虫实战案例——从移动端接口抓取微博评论,采用cookie登陆,数据存入excel表格,超详细(15)

文章目录 1、任务目标2、网页分析3、代码编写3.1 代码分析3.2 完整代码1、任务目标 1、目标网站:微博文章(https://m.weibo.cn/detail/4813628149072458),这是微博某一篇博文,用于本文测试 2、要求:爬取该博文下,所有一级评论和二级评论,以及每条评论的作者,最后保存至E…

熵权法计算评价指标权重——使用Excel VBA实现

[ 熵权法 ] 信息是系统有序程度的一个度量&#xff0c;熵是系统无序程度的一个度量&#xff1b;根据信息熵的定义&#xff0c;对于某项指标&#xff0c;可以用熵值来判断某个指标的离散程度&#xff0c;其信息熵值越小&#xff0c;指标的离散程度越大&#xff0c; 该指标对综合…

java脚手架系列4--测试用例、拦截器

异常处理、拦截器、数据库连接 1 测试用例 单元测试是一个老生常谈的问题&#xff0c;无论是后端对自己的代码质量把的第一道关也好&#xff0c;也是对测试减缓压力。这里就不过多讲述测试用例的重要性&#xff0c;但是有2个框架我们必须了解一下。 1.1 JUnit和mockito 我们…

gitlab保护分支设置

版本&#xff1a;gitlab10.2.2 一旦设置master分支被保护&#xff0c;除了管理员之外的任何用户都无法直接向master提交代码&#xff0c;只要提交代码就会报错 # git push -u origin master Total 0 (delta 0), reused 0 (delta 0) remote: GitLab: You are not allowed to pu…

[LeetCode] 733. 图像渲染

题目描述&#xff1a; 有一幅以 m x n 的二维整数数组表示的图画 image &#xff0c;其中 image[i][j] 表示该图画的像素值大小。你也被给予三个整数 sr , sc 和 color 。你应该从像素 image[sr][sc] 开始对图像进行上色 填充 。 为了完成 上色工作&#xff1a; 从初始像素…

【python】OpenCV—Fun Mirrors

文章目录 1、准备工作2、原理介绍3、代码实现4、效果展示5、参考 1、准备工作 pip install vacm2、原理介绍 在OpenCV中&#xff0c;VCAM 库是一个用于简化创建三维曲面、定义虚拟摄像机、设置参数以及进行投影任务的工具。它特别适用于实现如哈哈镜等图像变形效果。 一、VC…

简易STL实现 | PriorityQueue 的实现

1、priority_queue 的底层是堆&#xff0c;标准库中 直接使用 std::make_heap, std::push_heap, std::pop_heap 来实现 priority_queue 2、std::make_heap、std::push_heap 和 std::pop_heap 这三个函数 用于 处理堆数据结构&#xff08;Heap&#xff09;。堆 是一种特殊的完全…

4、.Net 快速开发框架:DncZeus - 开源项目研究文章

DncZeus 是一个基于 ASP.NET Core 和 Vue.js 的前后端分离的通用后台管理系统框架&#xff0c;其愿景是成为一个易于使用且功能丰富的 .NET Core 通用后台权限管理模板系统基础框架。项目名称 "DncZeus" 由 "Dnc"(.NET Core 的缩写)和 "Zeus"(古…

JavaWeb环境下的Spring Boot在线考试系统开发

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理基于JavaWeb技术的在线考试系统设计与实现…

【学习】word保存图片

word中有想保存的照片 直接右键另存为的话&#xff0c;文件总是不清晰&#xff0c;截屏的话&#xff0c;好像也欠妥。 怎么办? 可以另存为 网页 .html 可以得到&#xff1a; 原图就放到了文件夹里面

Java学习Day47:戏耍黑手道人(项目记录)

1.项目背景 2.技术选择 3.环境搭建 1.创建空项目 创建health_parent父文件用来控制依赖&#xff0c;类型为quickStart 打包方式为&#xff0c;pom&#xff1a;用在父级工程或聚合工程中&#xff0c;用来做jar包的版本控制&#xff0c;必须指明这个聚合工程的打包方式为pom。…

计算机网络-RSTP工作过程与原理

前面我们已经学习了RSTP的一些基础概念以及对于STP的改进之处&#xff0c;因为RSTP兼容STP&#xff0c;所以实际上两者工作原理是一致的&#xff0c;这里只简单过一遍&#xff0c;然后进行一些基础实验即可&#xff0c;大致还是遵循选举根桥、确定端口角色与状态、全网收敛的思…

ROS理论与实践学习笔记——6 ROS机器人导航(仿真)之导航实现

准备工作&#xff1a;请先安装相关的ROS功能包 安装 gmapping 包(用于构建地图):sudo apt install ros-<ROS版本>-gmapping 安装地图服务包(用于保存与读取地图):sudo apt install ros-<ROS版本>-map-server 安装 navigation 包(用于定位以及路径规划):sudo apt in…

一文详解Ntlm Relay

Ntlm Rleay简介 Ntlm Rleay翻译过来就是Ntlm 中继的意思&#xff0c;也肯定是跟Ntlm协议是相关的&#xff0c;既然要中继&#xff0c;那么攻击者扮演的就是一个中间人的角色&#xff0c;类似于ARP欺骗&#xff0c;ARP欺骗就是在一个广播域中发送一些广播&#xff0c;然后大声问…

解锁C++多态的魔力:灵活与高效的编码艺术(上)

文章目录 前言&#x1f338;一、多态的定义与概念&#x1f33b;1.1 多态的核心思想&#xff1a;&#x1f33b;1.2 多态的两种主要形式&#xff1a; &#x1f338;二、多态的使用条件&#x1f33b;2.1 基类指针或引用2.1.1 为什么需要基类指针或引用 &#x1f33b;2.2 虚函数&am…

UE5 猎户座漂浮小岛 04 声音 材质

UE5 猎户座漂浮小岛 04 声音 材质 1.声音 1.1 导入 wav格式 1.2 循环播放 1.3 mp3转wav 1.4 新手包素材&#xff08;火焰 &#xff09; particle&#xff1a;颗粒 2.材质 2.1 基本颜色 M_Yellow 2.2 混合模式与双面材质 2.3 金属感、高光、粗糙度 M_AluminumAlloy 2.4 自…

视频网站开发:Spring Boot框架的高效实现

5 系统实现 5.1用户信息管理 管理员管理用户信息&#xff0c;可以添加&#xff0c;修改&#xff0c;删除用户信息信息。下图就是用户信息管理页面。 图5.1 用户信息管理页面 5.2 视频分享管理 管理员管理视频分享&#xff0c;可以添加&#xff0c;修改&#xff0c;删除视频分…

Codeforces Round 770 (Div. 2)

比赛链接&#xff1a;Dashboard - Codeforces Round 770 (Div. 2) - Codeforces A. Reverse and Concatenate 题意&#xff1a; 思路&#xff1a; 假设 s "abba" 经过1次操作后 -> "abbaabba" s "abcd" 经过一次操作后 -> "abcd…

JavaWeb合集12-Redis

十二、Redis 1、Redis 入门 Redis是一个基于内存的key-valule 结构数据库。 特点&#xff1a;基于内存存储&#xff0c;读写性能高 场景&#xff1a;适合存储热点数据(热点商品、资讯、新闻) Redis安装包分为Windows版和Linux版&#xff1a; Windows版 下载地址: https://gith…