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

【优先算法】专题——双指针

1.移动零

移动零

题目描述:

思路:

本题我们把数组分块,将非零元素移动到左边,为零元素移动右边。

我们使用双指针算法(利用数组下标来充当指针)

两个指针的作用:

cur:从左往右扫描数组,遍历数组

dest:已经处理的区间内,非零元素的最后一个位置

我们将数组分为三个区间:

如何做到:

cur从前往后遍历的过程中:

1,遇到0元素:cur++;

2.遇到非零元素:

  • swap(dast+1,cur);
  • dest++,cur++;

参考代码如下:

class Solution {
public:void moveZeroes(vector<int>& nums) {int cur = 0;int dest = -1;while(cur < nums.size()){if(nums[cur] == 0){++cur;}else{swap(nums[cur],nums[dest+1]);++cur;++dest;}}}
};

这个题其实我们用到了快排的思想


2.复写零

复写零

题目描述:

题目分析:题目说不要超过数组长度其实就是告诉我们不要越界,题目还告诉我们不能创建额外数组让我们就地修改原数组,我们不需要返回任何内容。

思路:我们依旧使用双指针算法,先根据“异地”操作,然后优化成双指针下的“就地”操作

1.先找到最后一个复写的数

  • 先判断cur位置的值
  • 决定dest向后移动一步或者两步
  • 判断一下dest是否已经到结束为止
  • cur++

2.然后从后向前复写

这里有个例外需要额外处理一下

以上这种情况在我们进行从后向前复写的时候会发生越界访问把这个位置给修改为0,在LeetCode上越界访问会直接报错,所以我们要单独处理一下这种情况

n-1位置直接修改为0,在让dest -= 2,cur--;

参考代码如下:

class Solution {
public:void duplicateZeros(vector<int>& arr) {int dest = -1;int cur = 0;//找到最后一个复写while(cur < arr.size()){if(arr[cur] == 0){dest += 2;}else{dest++;}if(dest >= arr.size()-1){break;}cur++;}//处理越界if(dest == arr.size()){arr[arr.size()-1] = 0;--cur;dest -= 2;}while(dest >= 0){if(arr[cur] == 0){arr[dest--] = 0;arr[dest--] = 0;cur--;}else{arr[dest--] = arr[cur--];}}}
};

3.快乐数

快乐数

题目描述:

题目分析:

题目意思大概就是这样。

思路:我们之前在数据结构中不是学了一个判断链表是否有环,这里就可以运用起来,使用快慢双指针。

1.定义快慢指针

2.快慢指针每次向后移动一步,快指针每次向后移动两步

3.判断相遇时候的值即可。

参考代码如下:

class Solution {
public:int bitSum(int n){int sum = 0;while(n){int t = n % 10;sum += t * t;n /= 10;}return sum;}bool isHappy(int n) {int slow = n,fast = bitSum(n);while(slow != fast){slow = bitSum(slow);fast = bitSum(bitSum(fast));}return slow == 1;}
};

4.盛最多水的容器

盛最多水的容器

题目描述:

题目分析:如示例1:下标为1的它的高度是8和下标为8的它的高度为7这个容器的高度不能超过7,也就是取他们的最小值,那么从下标1到下标8的宽度为7,也就是下标为1到下标为8的距离,得出高为7宽为7相乘得出49那么最多容纳水量49,而我们要取这个容器里面的最大水量。

思路:

解法一:大部分人最容易想到的就是用两个for循环暴力枚举,让1和后面的数依次枚举,但是这样时间复杂度是O(N^2)效率太低。

解法二:

利用单调性,使用双指针来解决问题时间复杂度O(N)

我们使用双指针一个left一个right,选取这两个数的最小值也就是高度,然后让right减left得出宽度进行计算即可,把结果存储起来选出最大值也就是最大水量了,然后我们让小的那个数往前走,依次内推,这里我们知道如果一个数的宽度总是在减小那么这个水容量也会减小,而我们需要的是最大水容量。

参考代码:

class Solution {
public:int maxArea(vector<int>& height) {int left = 0,right = height.size()-1,ret = 0;while(left < right){int v = min(height[left],height[right]) * (right - left);ret = max(v,ret);if(height[left] < height[right]) ++left;else --right;}return ret;}
};

5. 有效三角形的个数

有效三角形的个数

题目描述:

思路:

解法一:暴力枚举,下面是一个伪代码,它的时间复杂度是O(N^3),效率太低

解法二:我们先把数组排序一下然后使用双指针算法,我们让left+right的结果和最后一个也就是最大值进行比较如果大于说明right-left这个区间的值都能组成我们直接让right--,如果left-right的结果小于最大值说明right-left这个区间不能组成所以我们left++,比较完之后我们在让倒数第二个元素做为最大值对他们进行比较,以此内推。时间复杂度为O(N^2)

参考代码:

class Solution {
public:int triangleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());int ret = 0,n = nums.size()-1;for(int i = n;i >= 2;i--){int left = 0,right = i-1;while(left < right){if(nums[left] + nums[right] > nums[i]){ret += right -left;--right;}else{++left;}}}return ret;}
};

6.查找总价格为目标的两个商品

查找总价格为目标的两个商品

题目描述:

解法一:如下是伪代码

解法二:本题解法使用双指针,我们让最左边的值和最右边的值进行相加然后和target进行比较那么比较的结果无法就是三种,第一种sum > t,第二种sum<t,第三张sum==t(sum就是左边和右边之和),如果大于t说明left到right都大于那么我们-right即可,如果小于t说明left到right都小于t所以++left即可,以此内推。

参考代码:

class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int n = price.size()-1;      int left = 0,right = n;vector<int>v;while(left < right){int sum = price[left] + price[right];if(sum > target){--right;}else if(sum < target){++left;}else{return {price[left],price[right]};}}return {-1,-1};}
};

7.三数之和

三数之和

题目描述:


题目分析:

我们看示例1可以看到三个数相加之和要等于0,题目中说不可以重复那是什么意思呢,如上我们可以看到-1 0 1和0 1 -1还有-1 1 0他们都等于0但是他们里面的元素是相同的只不过位置不同这样就重复了只需一种即可。

思路:

解法一:排序+暴力解法+利用set去重,时间复杂度 o(N^3),暴力解法其实就是一个一个去试三个for循环

解法二:我们依旧使用双指针,如下:

  1. 排序
  2. 固定一个数a(a<=0,因为已经排过序了如果a>0那么left+right只会更加大,因为left是从a后面开始的)
  3. 在该数后面的区间内,利用“双指针算法”快速找到两个的和等于-a即可。

处理细节问题:

1.去重

  • 找到一种结果之后left和right指针要跳过重复元素
  • 当使用完一次双指针算法之后,i也需要跳过重复的元素
  • 注意:避免越界

2.不漏

  • 找到一种结果之后,不要“停”,缩小区间,继续寻找

 参考代码:

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());int n = nums.size();vector<vector<int>> ret;for(int i = 0;i <n;){int left = i+1,right = n-1,target = -nums[i];if(nums[i] > 0) break;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]});++left,--right;//去重left,rightwhile(left < right && nums[left] == nums[left -1]) ++left;while(left < right && nums[right] == nums[right + 1]) --right;}}//去重ii++;while(i < n && nums[i] == nums[i-1]) ++i;}return ret;}
};

8.四数之和

四数之和

题目描述:

这个题和三数之和的题类似

解法一:排序+暴力枚举+利用set去重

解法二:排序+双指针

  1. 依次固定一个数a;
  2. 在a后面的区间内,利用“三数之和”找到三个数使这三个数等于target-a即可

补充一下上面说的三数之和:

  1. 依次固定一个数b
  2. 在b后面的区间内,利用“双指针”找到两个数使这两个的和等于target-a-b即可。

时间复杂度O(N^3) 

参考代码:

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {sort(nums.begin(),nums.end());vector<vector<int>>ret;int n = nums.size();for(int i = 0;i<n;){for(int j = i+1;j<n;){long long amin = (long long)target - nums[i] - nums[j];int left = j +1,right = n-1;while(left < right){int sum = nums[left] + nums[right];if(left < right && sum > amin)--right;else if(left < right && sum < amin) ++left;else{ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});//去重left,rightwhile(left < right && nums[left] == nums[left-1]) ++ left;while(left < right && nums[right] == nums[right+1]) -- right;}}//去重jj++;while(j < n && nums[j] == nums[j-1]) ++ j;}//去重ii++;while(i < n && nums[i] == nums[i-1]) ++ i;}return ret;}};

结束语:

掌握双指针算法对于解决复杂问题至关重要,刷题则是积累经验、提升能力的关键途径。通过不断练习,我们不仅能提升自己的解题速度和准确性,更能培养灵活运用各种算法的能力,为解决更为复杂的问题打下坚实基础。

相关文章:

【优先算法】专题——双指针

1.移动零 移动零 题目描述&#xff1a; 思路&#xff1a; 本题我们把数组分块&#xff0c;将非零元素移动到左边&#xff0c;为零元素移动右边。 我们使用双指针算法&#xff08;利用数组下标来充当指针&#xff09; 两个指针的作用&#xff1a; cur&#xff1a;从左往右…...

CSP/信奥赛C++语法基础刷题训练(23):洛谷P1217:[USACO1.5] 回文质数 Prime Palindromes

CSP/信奥赛C语法基础刷题训练&#xff08;23&#xff09;&#xff1a;洛谷P1217&#xff1a;[USACO1.5] 回文质数 Prime Palindromes 题目描述 因为 151 151 151 既是一个质数又是一个回文数&#xff08;从左到右和从右到左是看一样的&#xff09;&#xff0c;所以 151 151 …...

C语言练习.if.else语句.strstr

今天在做题之前&#xff0c;先介绍一下&#xff0c;新学到的库函数strstr 想要使用它&#xff0c;要先给它一个头文件<string.h> char *strstr(const char*str1,const char*str2); 首先&#xff1a;1.strstr的返回值是char&#xff0c;字符类型的。 2.两个实参&#xff…...

利用浏览器录屏

以下内容参考自网络 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title></title> </head> <body> <div class"left"> <di…...

python中的map、split、join函数的作用 => ACM输入输出流

map(func,iter) lst_str ["1", "2", "3"] # 得到lst_num为[1, 2, 3] lst_num list(map(int, lst_str))如果想把一个列表里的所有元素批量地调用某一个函数&#xff0c;并映射得到一个新的列表&#xff08;原列表中元素相对位置不变&#xff0…...

Ubuntu20.04下安装向日葵

向日葵远程控制app官方下载 - 贝锐向日葵官网 下载Ununtu版的图形版本的安装deb包SunloginClient_15.2.0.63064_amd64.deb 直接执行 sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb 的话会报错: 如果在Ubuntu20.04里直接执行sudo apt install libgconf-2-4安装libgco…...

常用并发设计模式

避免共享的设计模式 不变性&#xff08;Immutability&#xff09;模式&#xff0c;写时复制&#xff08;Copy-on-Write&#xff09;模式&#xff0c;线程本地存储&#xff08;Thread-Specific Storage&#xff09;模式本质上都是为了避免共享。 1、使用时需要注意不变性模式…...

Redis Search系列 - 第七讲 Windows(CygWin)编译Friso

目录 一、背景二、安装CygWin三、编译Friso四、运行Friso五、Friso分词效果测试 一、背景 最近在做RedisSearch的中文分词效果调研&#xff0c;底层的中文分词插件使用的就是Friso&#xff0c;目前手里的Linux环境上yum镜像仓库有问题导致没法安装gcc&#xff0c;又急于验证Fr…...

利用Docker容器技术部署发布web应用程序

Docker是什么&#xff1f; docker 是一个开源的应用容器引擎&#xff0c;可以帮助开发者打包应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化&#xff0c;容器是完全使用沙箱机制&#xff0c;相互之间不会有任何…...

[免费]SpringBoot+Vue毕业设计论文管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue毕业设计论文管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue毕业设计论文管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 现代经济快节奏发展以及不断完善升级的信…...

BFS 算法专题(五):BFS 解决拓扑排序

目录 1. 拓扑排序简介 1.1 有向无环图 (DAG 图) 1.2 AOV 网(顶点活动图) 1.3 拓扑排序 1.3.1 如何实现 2. 力扣实战应用 2.1 课程表 2.1.1 算法原理 2.1.2 算法代码 2.2 课程表 II 2.2.1 算法原理 2.2.2 算法代码 2.3 火星词典 (hard) (原剑指offer) 2.3.1 算法原理…...

【Mysql】开窗聚合函数----SUM,AVG, MIN,MAX

1、概念 在窗口中&#xff0c;每条记录动态地应用聚合函数&#xff08;如&#xff1a;SUM(),AVG(),MAX(),MIN(),COUNT(),&#xff09;可以动态计算在指定的窗口内的各种聚合函数值。 2、操作 以下操作将基于employee表进行操作。 sum() 进行sum的时候&#xff0c;没有order …...

java操作doc——java利用Aspose.Words操作Word文档并动态设置单元格合并

在实际工作中&#xff0c;如果业务线是管理类项目或者存在大量报表需要导出的业务时&#xff0c;可以借助第三方插件实现其对应功能。 尤其是需要对word文档的动态操作或者模板数据的定向合并&#xff0c;使用Aspose会相对来说容易一些&#xff0c;而且相关文档比较完整&#…...

探索 .NET 9 控制台应用中的 LiteDB 异步 CRUD 操作

本文主要是使用异步方式&#xff0c;体验 litedb 基本的 crud 操作。 LiteDB 是一款轻量级、快速且免费的 .NET NoSQL 嵌入式数据库&#xff0c;专为小型本地应用程序设计。它以单一数据文件的形式提供服务&#xff0c;支持文档存储和查询功能&#xff0c;适用于桌面应用、移动…...

《进程隔离机制:C++多进程编程安全的坚固堡垒》

在当今数字化时代&#xff0c;软件系统的安全性愈发成为人们关注的焦点。尤其是在 C多进程编程领域&#xff0c;如何确保进程间的安全交互与数据保护&#xff0c;是每一位开发者都必须面对的重要课题。而进程隔离机制&#xff0c;犹如一座坚固的堡垒&#xff0c;为 C多进程编程…...

构建无障碍的数字世界:深入探讨Web可访问性指南

文章目录 前言一、什么是Web可访问性&#xff1f;二、Web内容无障碍指南&#xff08;WCAG&#xff09;三、ARIA属性的应用四、实践中的Web可访问性结语 前言 在当今高度互联的世界里&#xff0c;互联网已成为人们日常生活不可或缺的一部分。然而&#xff0c;对于数百万残障人士…...

跨境出海安全:如何防止PayPal账户被风控?

今天咱们聊聊那些让人头疼的事儿——PayPal账户被风控。不少跨境电商商家反馈&#xff0c;我们只是想要安安静静地在网上做个小生意&#xff0c;结果不知道为什么&#xff0c;莫名其妙账户就被冻结了。 但其实每个封禁都是有原因的&#xff0c;今天就来给大家分享分享可能的原…...

学习日记_20241123_聚类方法(MeanShift)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…...

AI编程和AI绘画哪个更适合创业?

AI编程和AI绘画各有优势&#xff0c;适合创业的方向取决于你的资源、兴趣、市场需求和技术能力。以下是两者的对比分析&#xff0c;帮助你选择更适合的方向&#xff1a; AI编程 优势 1、广泛应用领域&#xff1a; 涉及自动化、数据分析、自然语言处理、计算机视觉等多个领域&a…...

macOS 无法安装第三方app,启用任何来源的方法

升级新版本 MacOS 后&#xff0c;安装下载的软件时&#xff0c;不能在 ”安全性与隐私” 中找不到 ”任何来源” 选项。 1. 允许展示任何来源 点击 启动器 (Launchpad) – 其他 (Other) – 终端 (Terminal)&#xff1a; 打开终端后&#xff0c;输入以下代码回车&#xff1a; …...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

嵌入式面试常问问题

以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...