【题目/训练】:双指针

引言

我们已经在这篇博客【算法/学习】双指针-CSDN博客里面讲了双指针、二分等的相关知识。

现在我们来做一些训练吧 

经典例题

1. 移动零

 思路:
  使用 0 当做这个中间点,把不等于 0(注意题目没说不能有负数)放到中间点的左边,等于 0 的放到其右边。
这的中间点就是 0 本身,所以实现起来比快速排序简单很多,然后使用双指针 i 和 j,只要 nums[i]!=0,我们就交换 nums[i] 和 nums[j]

class Solution {
public:void moveZeroes(vector<int>& nums) {if (nums.size() == 0) return;// 双指针,前后交换即可int j = 0;for (int i = 0; i < nums.size(); i++) {//当前元素!=0,就把其交换到左边,等于0的交换到右边if (nums[i] != 0) {swap(nums[i], nums[j++]);}}}
};

2. 复写零

思路:

class Solution {
public:void duplicateZeros(vector<int>& arr) {// 1. 找到最后一个复写数 int cur = 0, dest = -1, n = arr.size();while (cur < n){if (arr[cur]) dest++;else dest += 2;if (dest >= n - 1) break;cur++;}// 2. 处理边界清空if (dest == n){arr[n - 1] = 0;cur--, dest -= 2;}// 3. 从后往前完成复写操作while (cur >= 0){if (arr[cur]) arr[dest--] = arr[cur--];else{arr[dest--] = 0;arr[dest--] = 0;cur--;}}}
};

3. 有效三角形的个数

思路:

首先对数组排序。
固定最短的两条边,二分查找最后一个小于两边之和的位置。可以求得固定两条边长之和满足条件的结果。枚举结束后,总和就是答案。

class Solution {
public:int triangleNumber(vector<int>& nums) {// 1. 排序来优化sort(nums.begin(), nums.end());// 2. 利用双指针来解决问题 int ret = 0, n = nums.size();for (int i = n - 1; i >= 2; i--) // 先固定最大的数{// 利用双指针快速统计符合要求的三元组个数int l = 0, r = i - 1;while (l < r){if (nums[l] + nums[r] > nums[i]){ret += r - l;r--;}else l++;}}return ret;}
};

4.   两数之和II

 思路:

题目本质就是:查找和为 target 的两个数,由于已经是升序排列,直接双指针即可,left 指向0,right 指向 n -1 ,两数之后小于则 left ++,大于则 right --,相等就返回即可

注:返回的两个值,是从1开始计算,故需要加 1

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int l = 0, r = nums.size() - 1;while (l < r){if (nums[l] + nums[r] > target) r--;else if (nums[l] + nums[r] < target) l++;else return {l + 1, r + 1};}return {}; //若没有返回空即可}
};

5、两数之和

 思路:

该题与上一题有区别,是乱序的。为了使用左右端点双指针,需要排序,并且题目不是求结果而是求原索引,所以需要在排序前记录原索引。

因此我们使用先定义一个ind 数组,通过sort排序在ind数组中记录原数组中升序的索引排列,然后双指针即可。

注:返回时,小的索引在前,大的在后

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {// 1. 记录升序索引int n = nums.size();vector<int> ind(n); //下标数组for (int i = 0; i < n; i++) ind[i] = i; //下标从 i 开始sort(ind.begin(), ind.end(), [&](int i, int j)->bool{return nums[i] < nums[j];});// 2. 双指针查找等于target 的两个ind 映射下标int l = 0, r = n - 1;while (nums[ind[l]] + nums[ind[r]] != target){if (nums[ind[l]] + nums[ind[r]] > target) r--;else if (nums[ind[l]] + nums[ind[r]] < target) l++;}// 3. 对两个ind 映射下标,小的数在前,大的数在后if (ind[l] > ind[r]) swap(ind[l], ind[r]);return {ind[l],ind[r]};}
};

6、三数之和

 思路:

  1. 排序
  2. 固定一个数为 a (优化:固定的数a一定小于等于0,因为固定的a若是正数,其后面的数也是正数,三数之和一定不会等于0)
  3. 在该数后面区间内,利用双指针算法,找到两数之和等于 -a 即可,这里就可以用到上面题的写法了。

细节处理:

  • 返回的是值不是下标
  • 需要去重,做法:找到一种结果之和,left 和 right指针跳过重复元素,并且当使用完一次双指针之后,后面 i 往后移动也要跳过重复元素
  • 避免指针越界

 

class Solution {
public:vector<vector<int>> ans;vector<vector<int>> threeSum(vector<int>& nums) {// 1. 排序sort(nums.begin(), nums.end());// 2. 利用双指针int n = nums.size(), i = 0;while (i < n) // 固定数 a{if (nums[i] > 0) break; // 优化int l = i + 1, r = n - 1, target = -nums[i];while (l < r){if (nums[l] + nums[r] > target) r--;else if (nums[l] + nums[r] < target) l++;else{ans.push_back({ nums[i],nums[l],nums[r] });// 缩小区间,去重left, right操作l++, r--;while (l < r && nums[l] == nums[l - 1]) l++;while (l < r && nums[r] == nums[r + 1]) r--;}}// 去重 i i++;while (i < n && nums[i] == nums[i - 1])i++;}return ans;}
};

7、四数之和

  思路

本题与「三数之和」相似,解法也相似。

注:需要避免溢出,因此求两个数的和是否为aim时,对aim需要 long long 强转

class Solution {
public:vector<vector<int>> ans;vector<vector<int>> fourSum(vector<int>& nums, int target) {// 1. 排序sort(nums.begin(), nums.end());int n = nums.size(), i = 0;while(i < n){// 利用三数之和int j = i + 1;while(j<n){int l = j + 1, r = n - 1;long long aim = (long long)target - nums[i] - nums[j]; //避免溢出                while (l < r){if (nums[l] + nums[r] > aim) r--;else if (nums[l] + nums[r] < aim) l++;else{ans.push_back({ nums[i],nums[j],nums[l++],nums[r--] });// 缩小区间,去重left, right操作while (l < r && nums[l] == nums[l - 1]) l++;while (l < r && nums[r] == nums[r + 1]) r--;}}j++;while (j < n && nums[j] == nums[j - 1]) j++;}i++;while(i < n && nums[i] == nums[i - 1]) i++;}return ans;}
};

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

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

相关文章

基于java的酒店管理系统设计与实现

系统分析与设计 需求分析 1.系统概要 根据餐饮系统的流程&#xff0c;完成从用户登录到开台点菜&#xff0c;到结账收银&#xff0c;到统计一条线的信息化管理&#xff0c;因此整个餐饮管理信息系统的研发内容就是开发一整套餐饮管理信息系统&#xff0c;实现餐饮业务的计算…

【Vue3】集成 Element Plus

【Vue3】集成 Element Plus 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的…

后端开发刷题 | 合并两个排序的链表

描述 输入两个递增的链表&#xff0c;单个链表的长度为n&#xff0c;合并这两个链表并使新链表中的节点仍然是递增排序的。 数据范围&#xff1a; 0≤n≤1000&#xff0c;−1000≤节点值≤1000 如输入{1,3,5},{2,4,6}时&#xff0c;合并后的链表为{1,2,3,4,5,6}&#xff0c;…

MySQL各个版本root账号没有最高权限的解决方法

一、详细报错 ERROR 1045 (28000): Access denied for user ‘root’‘localhost’ (using password: YES) 报错原因&#xff08;分析过程&#xff09;&#xff1a; rootlocalhost用户密码修改导致 解决方法&#xff1a; 跳过权限验证启动数据库&#xff0c;并修改密码。如下…

怎么快速定位bug?如何编写测试用例?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xff0c;那么在…

独立站PrestaShop安装

独立站PrestaShop安装 独立站PrestaShop安装系统需求下载PrestaShop浏览器下载命令行下载 解压PrestaShop创建数据库移动PrestaShop源码到web目录composer安装依赖包nginx配置访问域名进入安装页面选择语言许可协议系统兼容性店铺信息Content of your store系统配置数据库店铺安…

数据结构day03(栈 Stack 顺序栈、链式栈 )内含具体详细代码实现

目录 【1】栈 Stack 1》栈的定义 2》顺序栈 2》链式栈 4》顺序栈的链式栈的区别 【1】栈 Stack 1》栈的定义 栈&#xff1a;是只允许在一端进行插入或删除的线性表&#xff0c;首先栈是一种线性表&#xff0c;但限定这种线性表只能在某一端进行插入和删除操作。 栈顶&…

仿照ContentLoadingProgressBar 的特点在Android项目中自定义Loading对话框

ContentLoadingProgressBar 是 Android 中的一个控件&#xff0c;继承自 ProgressBar。它在 ProgressBar 的基础上添加了一些特殊功能&#xff0c;主要用于在加载内容时显示进度。它的一些主要特点如下&#xff1a; 自动隐藏和显示&#xff1a;ContentLoadingProgressBar 会在…

JavaScript_7_练习:随机抽奖案例

效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>练习&#xff1a;随机抽奖案例</tit…

vue项目配置基础路由vue-router

1、运行以下命令安装vue-router yarn add vue-router 2、在src目录下的components中新建两个vue页面 3、在src目录下新建router文件夹&#xff0c;在router文件夹下面新建index.js文件 4、配置main.js文件 //引入Vue import Vue from "vue"; //引入App import App…

全新分支版本!微软推出Windows 11 Canary Build 27686版

已经很久没有看到 Windows 11 全新的分支版本了&#xff0c;今天微软发布 Windows 11 Canary 新版本&#xff0c;此次版本号已经转移到 Build 27xxx&#xff0c;首发版本为 Build 27686 版。 此次更新带来了多项改进&#xff0c;包括 Windows Sandbox 沙盒功能切换到 Microsof…

LearnOpenGL——SSAO学习笔记

LearnOpenGL——SSAO学习笔记 SSAO一、基本概念二、样本缓冲三、法向半球四、随机核心转动五、SSAO着色器六、环境遮蔽模糊七、应用SSAO遮蔽因子 SSAO 一、基本概念 环境光照是我们加入场景总体光照中的一个固定光照常量&#xff0c;它被用来模拟光的散射(Scattering)。散射应…

QT事件机制理解

事件和信号 从硬件层来看: 事件就是一种中断&#xff0c; 中断的产生形式: 1.用户操控硬件所产生的中断。 2.由系统自身所产生的中断&#xff0c;比如说定时器。 这种中断由系统内核监控&#xff0c;由系统内核接收到中断并向CPU发出的执行请求就叫信号。所以说事件是信号产生…

C++,std::bind 详解

文章目录 1. 概述2. 基本用法2.1 使用占位符2.2 示例 3. 总结 1. 概述 std::bind 是 C11 引入的一个功能&#xff0c;它允许你将函数&#xff08;或成员函数、函数对象&#xff09;与其参数绑定&#xff0c;生成一个新的可调用对象。这个功能在需要将函数及其参数一起传递给其…

[OC]萝卜圈玩行车记录仪

图1-1&#xff0c;你的手动小车 代码是 #机器人驱动主程序 #请在main中编写您自己的机器人驱动代码 import tkinter as tk import turtle v0 # 速度 accFalse;slowFalse;leftFalse;rightFalse # 按键状态 step0.5 # 一次速度变化量 def keyup_press(event):global acc;accTru…

正点原子linux开发板 qt程序交叉编译执行

1.开发板光盘 A-基础资料->5、开发工具->1、交叉编译器->fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh 拷贝到 Ubuntu 虚拟机 用文件传输系统或者共享文件夹传输到linux虚拟机 用ls -l查看权限&#xff0c;如果是白色的使…

保姆级-C#与Halcon的窗体界面展示阈值分割图像教程(机器视觉保姆级教程)

经历上一篇《零基础小白实现C#调用halcon dll的过程&#xff0c;并测试程序证明C#halcon联合开发成功》的发布已经过去三天啦&#xff0c; 零基础小白实现C#调用halcon dll的过程&#xff0c;并测试程序证明C#halcon联合开发成功-CSDN博客 在友友的催更下&#xff0c;我将用我…

rabbitmq镜像集群搭建

用到的ip地址 ip地址端口192.168.101.65&#xff08;主&#xff09;15672192.168.101.7515672192.168.101.8515672 安装erlang和rabbitmq 安装 安装三个包 yum install esl-erlang_23.0-1_centos_7_amd64.rpm -y yum install esl-erlang-compat-18.1-1.noarch.rpm -y rpm -…

探索CompletableFuture:高效异步编程的利器

目录 一、CompletableFuture基本功能安利 二、CompletableFuture使用介绍 &#xff08;一&#xff09;任务创建使用 1.supplyAsync创建带有返回值的异步任务 2.runAsync创建没有返回值的异步任务 &#xff08;二&#xff09;异步回调使用 1.异步回调&#xff1a;thenApp…

基于Sringboot+Vue个人驾校预约管理系统--论文pf

TOC springboot503基于SringbootVue个人驾校预约管理系统--论文pf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。…