[算法] 优先算法(二): 双指针算法(下)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:🍕 Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀Java EE(94平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 有效三角形的个数(难度:🔵2度)
  • 2.两数之和(难度:🟢1度)
  • 3. 三数之和(难度:🟠4度)
  • 4.四数之和(难度:🔴5度)

1. 有效三角形的个数(难度:🔵2度)

OJ链接

  • 题目描述

购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。
示例 1:
输入:price = [3, 9, 12, 15], target = 18
输出:[3,15] 或者 [15,3]
示例 2:
输入:price = [8, 21, 27, 34, 52, 66], target = 61
输出:[27,34] 或者 [34,27]

  • 算法原理
    先将数组排序
    我们可以固定⼀个==「最⻓边」,然后在⽐这条边⼩的有序数组中找出⼀个⼆元组==,使这个⼆元组之和⼤于这个最⻓边。由于数组是有序的,我们可以利⽤「对撞指针」来优化。
    设最⻓边枚举到i 位置,区间[left, right] 是i 位置左边的区间(也就是⽐它⼩的区间):
    • 如果nums[left] + nums[right] > nums[i] :
      • 说明[left, right - 1] 区间上的所有元素均可以与nums[right] 构成⽐nums[i] ⼤的⼆元组
      • 满⾜条件的有right - left 种
      • 此时right 位置的元素的所有情况相当于全部考虑完毕, right– ,进⼊下⼀轮判断
    • 如果nums[left] + nums[right] <= nums[i] :
      • 说明left 位置的元素是不可能与[left + 1, right] 位置上的元素构成满⾜条件的⼆元组
      • left 位置的元素可以舍去, left++ 进⼊下轮循环
  • 代码编写
class Solution {public int triangleNumber(int[] nums) {Arrays.sort(nums);int ret = 0;for (int n = nums.length-1;n >= 2;n--){//n固定最大边int left = 0;int right = n-1;while (left < right){if (nums[left] + nums[right] <= nums[n]){//舍去比right小的元素left++;}else{//比left大的元素全部符合条件ret+=right-left;right--;}}}return ret;}
}

2.两数之和(难度:🟢1度)

OJ链接

  • 题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]

  • 算法原理
    • 初始化left , right 分别指向数组的左右两端(这⾥不是我们理解的指针,⽽是数组的下
      标)
    • 当left < right 的时候,⼀直循环
      • 当nums[left] + nums[right] == target 时,说明找到结果,记录结果,并且返回;
      • 当nums[left] + nums[right] < target 时:
        • 对于nums[left] ⽽⾔,此时nums[right] 相当于是nums[left] 能碰到的最⼤值别忘了,这⾥是升序数组)。如果此时不符合要求,说明在这个数组⾥⾯,没有别的数符合nums[left] 的要求了(最⼤的数都满⾜不了你,你已经没救了)。因此,我们可以⼤胆舍去这个数,让left++ ,去⽐较下⼀组数据;
        • 那对于nums[right] ⽽⾔,由于此时两数之和是⼩于⽬标值的, nums[right] 还可以选择⽐nums[left] ⼤的值继续努⼒达到⽬标值,因此right 指针我们按兵不动;
      • 当nums[left] + nums[right] > target 时,同理我们可以舍去nums[right] (最⼩的数都满⾜不了你,你也没救了)。让right– ,继续⽐较下⼀组数据,⽽left 指针不变(因为他还是可以去匹配⽐nums[right] 更⼩的数的)。
  • 代码编写
class Solution {public int[] twoSum(int[] price, int target) {int left = 0;int right = price.length-1;while (left < right){if (price[left]+price[right] == target){return new int[]{price[left],price[right]};}else if (price[left]+price[right] < target){left++;}else{right--;}}return new int[0];}
}

3. 三数之和(难度:🟠4度)

OJ链接

  • 题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != 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 。

  • 算法原理
    与两数之和稍微不同的是,题⽬中要求找到所有「不重复」的三元组。那我们可以利⽤在两数之和那⾥⽤的双指针思想,来对我们的暴⼒枚举做优化:
    • 排序
    • 然后固定⼀个数a
    • 在这个数后⾯的区间内,使⽤「双指针算法」快速找到两个数之和等于-a 即可
      但是要注意的是,这道题⾥⾯需要有==「去重」操作==~
    • 找到⼀个结果之后, left 和right 指针要「跳过重复」的元素
    • 当使⽤完⼀次双指针算法之后,固定的a 也要「跳过重复」的元素

最后一点要注意的是在去重操作移动指针的时候,不要出现越界情况.
还有一点小优化就是,在i遍历到>0的数据的时候,就可以停止了,这是因为在剩下的数字中再也找不得两个数字加起来等于负数了.

  • 代码编写
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ret = new ArrayList<>();Arrays.sort(nums);for (int i = 0;i < nums.length;){if (nums[i] > 0){//遇到大于0的,一定没有两个数使得条件成立break;}int left = i + 1;int right = nums.length-1;while(left < right){if (nums[left] + nums[right] == -nums[i]){List<Integer> a = new ArrayList<>();a.add(nums[i]);a.add(nums[left]);a.add(nums[right]);ret.add(a);left++;right--;while(left < nums.length && nums[left] == nums[left-1]){//left去重,且不可以越界left++;}while(right > 0 && nums[right] == nums[right+1]){//right去重且不可以越界right--;}}else if (nums[left] + nums[right] < -nums[i]){//与前面两数之和的原理相同left++;}else{right--;}}//i去重i++;while(i < nums.length && nums[i] == nums[i-1]){//不可以越界i++;}}return ret;}
}

4.四数之和(难度:🔴5度)

  • 题目描述

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
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]]

  • 算法原理
    a. 依次固定⼀个数a
    b. 在这个数a 的后⾯区间上,利⽤
    「三数之和」找到三个数
    ,使这三个数的和等于target -a 即可。
  • 代码编写
class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> ret = new ArrayList<>();Arrays.sort(nums);for (int i = 0; i < nums.length;){for (int j = i+1;j < nums.length;){int left = j+1;int right = nums.length-1;long t = (long)target-nums[j]-nums[i];while(left < right){if (nums[left] + nums[right] == t){List<Integer> a = new ArrayList<>();a.add(nums[left]);a.add(nums[right]);a.add(nums[j]);a.add(nums[i]);ret.add(a);left++;right--;while(left < nums.length && nums[left] == nums[left-1]){left++;}while(right > 0 && nums[right] == nums[right+1]){right--;}}else if(nums[left] + nums[right] < t){left++;}else{right--;}}j++;while(j < nums.length && nums[j] == nums[j-1]){j++;}}i++;while(i < nums.length && nums[i] == nums[i-1]){i++;}}return ret;}
}

从今天的代码中,我们可以发现,这几道题目在不停的利用数组的单调性和双指针在优化暴力解法,排除掉暴力解法中的一些无效情况,以后在我们做题的时候,要充分利用单调性和双指针的配合.

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

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

相关文章

基于transformers框架实践Bert系列6-完形填空

本系列用于Bert模型实践实际场景&#xff0c;分别包括分类器、命名实体识别、选择题、文本摘要等等。&#xff08;关于Bert的结构和详细这里就不做讲解&#xff0c;但了解Bert的基本结构是做实践的基础&#xff0c;因此看本系列之前&#xff0c;最好了解一下transformers和Bert…

Python筑基之旅-MySQL数据库(一)

目录 一、MySQL数据库 1、简介 2、优点 2-1、开源和免费 2-2、高性能 2-3、可扩展性 2-4、易用性 2-5、灵活性 2-6、安全性和稳定性 2-7、丰富的功能 2-8、结合其他工具和服务 2-9、良好的兼容性和移植性 3、缺点 3-1、对大数据的支持有限 3-2、缺乏全文…

微服务如何做好监控

大家好&#xff0c;我是苍何。 在脉脉上看到这条帖子&#xff0c;说阿里 P8 因为上面 P9 斗争失败走人&#xff0c;以超龄 35 被裁&#xff0c;Boss 上找工作半年&#xff0c;到现在还处于失业中。 看了下沟通记录&#xff0c; 沟通了 1000 多次&#xff0c;但没有一个邀请投递…

uniapp中使用 iconfont字体

下载 iconfont 字体文件 打开 iconfont.css 文件&#xff0c;修改一下 把文件 复制到 static/iconfont/… 目录下 在App.vue中引入iconfont 5. 使用iconfont 使用 iconfont 有两种方式&#xff0c; 一种是 class 方式&#xff0c; 一种是使用 unicode 的方式 5.1 使用 class 的…

【Mac】Dreamweaver 2021 for mac v21.3 Rid中文版安装教程

软件介绍 Dreamweaver是Adobe公司开发的一款专业网页设计与前端开发软件。它集成了所见即所得&#xff08;WYSIWYG&#xff09;编辑器和代码编辑器&#xff0c;可以帮助开发者快速创建和编辑网页。Dreamweaver提供了丰富的功能和工具&#xff0c;包括代码提示、语法高亮、代码…

教你一分钟搭建适合IT人员的在线开发工具箱

文章目录 1. 使用Docker本地部署it-tools2. 本地访问it-tools3. 安装cpolar内网穿透4. 固定it-tools公网地址 本篇文章将介绍如何在Windows上使用Docker本地部署IT- Tools&#xff0c;并且同样可以结合cpolar实现公网访问。 在前一篇文章中我们讲解了如何在Linux中使用Docker搭…

Anaconda Jupyter 报错及解决方法记录

一、AttributeError: module lib has no attribute X509_V_FLAG_CB_ISSUER_CHECK 背景&#xff1a;Anaconda更新版本后&#xff0c;运行import oss2时报错 ~/anaconda3/lib/python3.8/site-packages/OpenSSL/crypto.py in X509StoreFlags() 1535 NOTIFY_POLICY _lib…

【Java基础】集合(1) —— Collection

存储不同类型的对象: Object[] arrnew object[5];数组的长度是固定的, 添加或删除数据比较耗时 集合: Object[] toArray可以存储不同类型的对象随着存储的对象的增加&#xff0c;会自动的扩容集合提供了非常丰富的方法&#xff0c;便于操纵集合相当于容器&#xff0c;可以存储多…

冯喜运:5.16黄金是否突破阻力?黄金原油趋势分析

【黄金消息面分析】&#xff1a;周四(5月16日)亚市盘中&#xff0c;现货黄金延续昨日升势&#xff0c;金价目前最高触及2397.44美元/盎司&#xff0c;为4月19日以来新高。FXStreet首席分析师Valeria Bednarik撰文&#xff0c;对黄金技术前景进行分析。Bednarik指出&#xff0c;…

「51媒体」北京财经媒体有哪些?媒体邀约宣传

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 北京作为中国的首都&#xff0c;拥有众多的财经媒体&#xff0c;这些媒体在财经新闻报道、经济分析、市场研究等方面发挥着重要作用。根据搜索结果&#xff0c;以下是一些北京地区的财经…

CV每日论文--2024.5.15

1、Can Better Text Semantics in Prompt Tuning Improve VLM Generalization? 中文标题&#xff1a;更好的文本语义在提示微调中能否提高视觉语言模型的泛化能力? 简介&#xff1a;这篇论文介绍了一种新的可学习提示调整方法,该方法超越了仅对视觉语言模型进行微调的传统方…

Lazyboy品牌发布会“球幕气膜”

Lazyboy品牌发布会“球幕气膜”为品牌活动提供了一个独特、现代化、环保的展示空间。这座球幕气膜不仅为发布会提供了一个视觉震撼的场地&#xff0c;也为与会嘉宾带来了全新的体验。作为轻空间&#xff08;江苏&#xff09;膜科技有限公司&#xff08;以下简称“轻空间”&…

使用Docker在阿里云ECS上部署Gitlab,提供代码托管、CICD 和 docker镜像服务

文章目录 使用Docker在阿里云ECS上部署Gitlab1.购买一个数据&#xff0c;挂载到/data用于存储gitlab相关数据2. 部署docker引擎3. 调整ssh的默认端口&#xff0c;将22端口留给gitlab4. 部署gitlab5. 进入docker容器获取gitlab的默认密码6. 登录gitlab&#xff0c;完成gitlab-ru…

linux ndk编译搭建测试

一、ndk下载 NDK 下载 | Android NDK | Android Developers 二、ndk环境变量配置 ndk解压&#xff1a; unzip android-ndk-r26d-linux.zip 环境变量配置&#xff1a; export NDK_HOME/rd/own/test/android-ndk-r26d/ export PATH$PATH:$NDK_HOME 三、编译测试验证 …

LeetCode-2589. 完成所有任务的最少时间【栈 贪心 数组 二分查找 排序】

LeetCode-2589. 完成所有任务的最少时间【栈 贪心 数组 二分查找 排序】 题目描述&#xff1a;解题思路一&#xff1a;贪心暴力解题思路二&#xff1a;栈二分查找解题思路三&#xff1a;简化版 题目描述&#xff1a; 你有一台电脑&#xff0c;它可以 同时 运行无数个任务。给你…

mac安装两个版本谷歌浏览器;在mac运行不同版本的chrome浏览器

场景 正常情况下&#xff0c;mac上只能安装一个版本的chrome浏览器&#xff0c;即使你安装了两个版本的&#xff0c;打开老旧版本时候也会自动切换成最新版的浏览器 故本文主要解决如何下载和在mac运行不同版本的chrome浏览器 文章目录 场景一、下载1.mac本身就有一个最新版ch…

Java语言saas模式云HIS系统源码 前端Angular+后台SpringBoot云HIS系统源码 HIS系统适合哪些类型的医院?

Java语言saas模式云HIS系统源码 前端Angular后台SpringBoot云HIS系统源码 HIS系统适合哪些类型的医院&#xff1f; 云HIS系统&#xff08;医院信息系统&#xff09;是对医院及其所属各部门的人、财、物进行综合管理&#xff0c;对在医疗活动各阶段产生的数据进行采集、储存、处…

CCF20181201——小明上学

CCF20181201——小明上学 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int r,y,g,n,k[101],t[101],sum0;cin>>r>>y>>g;cin>>n; for(int i0;i<n;i){cin>>k[i]>>t[i];if(k[i]0||k[i]1)sumt[i];…

ITSM的服务台如何让工作更流畅

在现代企业的信息技术管理框架内&#xff0c;IT服务管理&#xff08;IT Service Management, ITSM&#xff09;体系扮演着至关重要的角色&#xff0c;而其中的服务台则是这一复杂体系的心脏地带。服务台不仅仅是解答技术疑问的一线窗口&#xff0c;更是企业IT运维效率与用户满意…

FENDI CLUB啤酒,为何女生喜欢?

精酿啤酒已经成了女生喜欢的饮品&#xff0c;在日剧《无法成为野兽的我们》里&#xff0c;主人公小晶永远保持标准笑容&#xff0c;完美完成所有的工作。只有一个人的时候&#xff0c;她才会放下习惯性的微笑&#xff0c;显露自己的疲惫。小晶缓解疲惫&#xff0c;就是下班后去…