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

🌸个人主页: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;
    }
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python TCP编程简单实例

客户端&#xff1a;创建TCP链接时&#xff0c;主动发起连接的叫做客户端 服务端&#xff1a;接收客户端的连接 连接其他服务器 可以通过tcp连接其他服务器。 示例&#xff1a; import socket# 1.创建一个socket # 参数1&#xff1a;指定协议 AF_INET&#xff08;ipv4&#…

ftp是什么,ftp能做什么,ftp有什么用 -----在Windows搭建ftp服务器

大家好&#xff0c;我是风屿&#xff0c;今天教大家如何从零开始搭建一台属于自己的ftp&#xff0c;本期教大家搭建Windows客户端的&#xff0c;后面是linux的 首先第一步要有一台联网的Windows电脑 1打开控制面板&#xff0c;找到程序&#xff0c;点击打开或关闭Windows功能…

MQTT 5.0 报文解析 05:DISCONNECT

欢迎阅读 MQTT 5.0 报文系列 的第五篇文章。在上一篇中&#xff0c;我们已经介绍了 MQTT 5.0 的 PINGREQ 和 PINGRESP 报文。现在&#xff0c;我们将介绍下一个控制报文&#xff1a;DISCONNECT。 在 MQTT 中&#xff0c;客户端和服务端可以在断开网络连接前向对端发送一个 DIS…

QT项目-欢乐斗地主游戏

QT项目-欢乐斗地主游戏 游戏概述游戏规则牌型牌型的大小游戏角色游戏规则游戏的胜负游戏计分规则 游戏相关的类介绍卡牌类玩家类窗口类游戏控制类游戏策略类线程类音频类 游戏主要组件卡牌玩家窗口 游戏控制源码 游戏概述 游戏规则 不同地域游戏规则可能有些许差异&#xff0c…

CCF20220601——归一化处理

CCF20220601——归一化处理 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,a[1000],sum0;scanf("%d",&n);for(int i1;i<n;i){scanf("%d",&a[i]);suma[i];}double aver1.0,b0.0,d1.0;aversum/(n*1…

vue3使用mitt.js进行各种组件间通信

我们在vue工程中&#xff0c;除开vue自带的什么父子间&#xff0c;祖孙间通信&#xff0c;还有一个非常方便的通信方式&#xff0c;类似Vue2.x 使用 EventBus 进行组件通信&#xff0c;而 Vue3.x 推荐使用 mitt.js。可以实现各个组件间的通信 优点&#xff1a;首先它足够小&…

0406 组合放大电路

组合放大电路 共射-共基放大电路共集-共集放大电路 4.6.1 共射—共基放大电路 4.6.2 共集—共集放大电路 共射-共基放大电路 共集-共集放大电路 (a) 原理图 (b)交流通路 T1、T2构成复合管&#xff0c;可等效为一个NPN管

c#点击listview控件获取内容

构造函数添加&#xff1a; 点击事件&#xff1a; &#xff08;listview控件确保有内容&#xff0c;比如已查询到数据添加到了listview&#xff09; if (listView_data_base.Items.Count > 0){listView_data_base.FullRowSelect true;listView_data_base.Items[listView_da…

【C语言】VS编译器的scanf

我们在写代码的时候通常需要用到输入函数&#xff1a;scanf&#xff0c;但在vs编译环境下却必须写为&#xff1a;scanf_s&#xff0c;这是为什么呢&#xff1f;这里就是vs规定的了&#xff0c;VS认为这样写更安全&#xff0c;但如果我们非要写成scanf形式也是有办法的。 # 看我…

服务器c盘爆满了,这几种方法可以帮助C盘“瘦身”

我们在使用服务器的时候基本不会在C盘安装软件&#xff0c;那么用久了发现C盘满了&#xff0c;提示空间不足&#xff1f;那么这是怎么回事&#xff0c;为什么空间会占用这么快呢&#xff1f; 原因一&#xff1a; C盘满了&#xff0c;很可能是因为电脑里的垃圾文件过多。操作系…

从业务角度来看,DevOps 是什么?

如果您在我们的应用程序名称中看到“DevOps”&#xff0c;这意味着我们必须正确解释该术语&#xff0c;我们会这样做&#xff0c;但角度会有所不同。让我们从业务角度看看 DevOps 是什么。 通用名称 首先你应该知道&#xff0c;DevOps 没有明确的定义。是的。 大多数情况下&a…

TypeScript-类型断言

类型断言 当开发者比TS本身更清楚当前的类型是什么&#xff0c;可以使用断言(as)让类型更加精确和具体 const _link document.getElementById(link) console.log(_link.href) // 出错了&#xff0c;如下图 const _link document.getElementById(link) as HTMLAnchorElement…

K8S认证|CKA题库+答案| 14. 排查故障节点

14、排查集群中的故障节点 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node wk8s master …

iptablese防火墙【SNAT和DNAT】

目录 1.SNAT策略及应用 1.1SNAT原理与应用 1.2 SNAT策略的工作原理 1.3 实验操练 2.DNAT策略 2.1 DNAT策略的概述 2.2 DNAT原理与应用 2.3 实验操练 1.SNAT策略及应用 1.1SNAT原理与应用 SNAT 应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xf…

AJAX、

文章目录 AJAX1. AJAX简介AJAX特点 2. XML简介3. AJAX发送get请求4. post请求设置体参数5. 设置请求头信息6. AJAX请求服务端响应json数据7. ie缓存问题8. 请求超时问题和网络异常9. 取消请求10. 请求重复取消11. jQuery中的AJAX请求12. axios函数发送AJAX使用fetch函数发送AJA…

PostgreSQL学习:关于PostgreSQL以及认证

1、关于PostgreSQL PostgreSQL&#xff08;简称PG&#xff09;是强大的企业级开源关系数据库&#xff0c;世界排名第四&#xff0c;前三位Oracle 、SQLServer、MySQL都是商业数据库或受商业主体的控制&#xff0c;PG是学术社区开源数据库&#xff0c;开源协议自由度非常高&…

【oracle的安装记录】

oracle安装记录 一、下载以后&#xff0c;解压到同一路径下面 二、双击可执行安装文件&#xff0c;等待文件加载 三、双击以后&#xff0c;弹出信息 四、提示该窗口&#xff0c;点击【是】即可 五、未填写配置安全更新信息 六、弹出小窗口&#xff0c;选择【是】 七、安装选项…

机器学习之决策树算法

使用决策树训练红酒数据集 完整代码&#xff1a; import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn import tree, datasets from sklearn.model_selection import train_test_split# 准备数据&#xff0c;这里…

一个通过ADC采集NTC热敏电阻的温度传感器

前言: 如何设计一个电路,使用具有逐次逼近寄存器(SAR)模数转换器(ADC)的热敏电阻直接监测温度呢?温度传感电路需要使用负温度系数(NTC)热敏电阻与电阻器串联形成分压器,监测-25C至100C的温度范围。分压器具有产生与监测的温度成反比的输出电压的效果。电阻器分压器的…

面试准备-项目【面试准备】

面试准备-项目【面试准备】 前言面试准备自我介绍&#xff1a;项目介绍&#xff1a; 论坛项目功能总结简介数据库表设计注册功能登录功能显示登录信息功能发布帖子评论私信点赞功能关注功能通知搜索网站数据统计热帖排行缓存 论坛项目技术总结Http的无状态cookie和session的区别…