算法 —— 双指针

目录

移动零 

复写零

快乐数

盛最多水的容器

有效三角形的个数

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

三数之和

四数之和


移动零 

 下图以样例1为例,看下图如何做到保证非零元素相对顺序前提下,移动零元素。

 代码实现如下:

class Solution {
public:void moveZeroes(vector<int>& nums) {for (int cur = 0, dest = -1; cur < nums.size(); cur++)if (nums[cur])//非0就交换swap(nums[++dest], nums[cur]);}
};

复写零

注意边界情况:例如 [ 1 0 2 3 0 4 ] dest会越界访问,此时需要把cur和dest回归到上一步位置

代码实现如下:

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

快乐数

先看示例2为什么会输出false:

此题目一共三种情况:1、进入全是1的环     2、进入全部不是1的环     3、无限延伸下去不带环

但是题目告诉我们只有两种情况,为什么不会无限延伸下去,可以用鸽巢原理解释:

鸽巢原理: 把(n+1)个物体任意放进n个鸽巢中(n是非0自然数),一定有一个鸽巢中至少放进了2个物体。 

题目给出范围n最大为2 ^ 31 - 1,即 2.1 * 10 ^ 9,假设是9999999999,那么经过一次平方和后变成810,也就是说n最大值经过一次平方和后最大不超过810,最小不低于1。

那么把810看作巢穴,把一次平方和规则看作鸽,经过811次平方和后,会导致810个巢穴不够分,至少有一个巢穴是两个鸽:意味着经过810次以上的平方和规则后,势必出现重复,重复后就进环。

代码入下:

class Solution {
public:// 计算每个位置上的数字的平方和int summary(int n){int sum = 0;while (n){int tmp = n % 10;sum += tmp * tmp;n /= 10;}return sum;}bool isHappy(int n) {int slow = n, fast = summary(n);// 快指针走两步  慢指针走一步while (slow != fast){slow = summary(slow);fast = summary(summary(fast));}return slow == 1;}
};

盛最多水的容器

 设置两个左右指针,由于下标相减所得宽度是不断减小的,那么在有限长度内,保证宽度最大的前提下得到最大的长度

宽度变小,长度可能不变,也可能变小,根据上图得出以下代码:

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

有效三角形的个数

 首先先对数组进行排序,例如 a , b , c 现在是升序状态,两个比c小的数相加大于c,那么c 加两个小数中的任何一个小数都比另外一个小数大。此外暴力枚举的时间复杂度过大,本题不适合。

首先固定最大的数,以一个循环为例,先固定最大数10,左指针指向下标为0的元素(2),右指针指向下标为5的元素(9),a就是2,b就是9,c就是10,a + b > c,那么a——b这个区间里所有数加b都大于c,个数即为right - left。一轮过后,right--找到次小的数5,再使left从下标0开始,a + b小于c,那么让left++,使得left变大,如果left == right时还小于最大数10,说明剩下的数无法组合成三角形,接着固定9作为最大数c,循环上述步骤。

代码如下:

class Solution {
public:int triangleNumber(vector<int>& nums) {// 1.优化排序sort(nums.begin(), nums.end());// 2.利用双指针解决问题int count = 0;for (int i = nums.size() - 1; i >= 2; i--){int left = 0, right = i - 1;while(left < right){if (nums[left] + nums[right] > nums[i]){count += (right - left);right--;}elseleft++;}}return count;}
};

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

首先最重要一点:题目告诉我们此数组为升序,那么可以利用单调性来解决问题。 

左指针右移相当于做加法操作,因为指向了一个更大的数,同理右指针左移相当于做减法操作,因为指向了一个更小的数。代码实现如下:

class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {vector<int> ret;int left = 0, right = price.size() - 1;while (left < right){int sum = price[left] + price[right];// 右指针左移相当于做减法if (sum > target)right--;// 左指针右移相当于做加法else if (sum < target)left++;else{ret.push_back(price[left]);ret.push_back(price[right]);break;}}return ret;}
};

三数之和

 此题最关键的为去重问题和避免越界问题,那么如何避免这两个问题发生呢?

首先要保证left指针始终在right左边,然后left++或者right--之后才可以和left前一个数或者right后一个数比较,并且 i 始终小于该数组元素个数。

代码实现如下:

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> ret;// 1.排序sort(nums.begin(), nums.end());// 2.利用双指针解决问题for (int i = 0; i < nums.size() - 2;){// 大于0意味着后面全是正数   不可能相加为0if (nums[i] > 0)break;int left = i + 1, right = nums.size() - 1, target = -nums[i];while (left < right){vector<int> ans;int sum = nums[left] + nums[right];if (sum > target){right--;}else if (sum < target){left++;}else{ans.push_back(nums[i]);ans.push_back(nums[left]);ans.push_back(nums[right]);ret.push_back(ans);left++; right--;// 去重 left 和 rightwhile (left < right && nums[left] == nums[left - 1])left++;while (left < right && nums[right] == nums[right + 1])right--;}}// 去重 ii++;while (i < nums.size() && nums[i] == nums[i - 1])i++;}return ret;}
};

四数之和

 此题唯一有问题的地方在于数据的大小可能会超过int类型的最大值,那么我们需要将他强制类型转换成long long类型的数据,这样便于后面的比较。其余部分和三数之和并无多大区别。

代码如下:

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {// 1.排序sort(nums.begin(), nums.end());// 2.利用双指针解决问题vector<vector<int>> ret;// 解决特殊情况   // 1.1 特殊情况  元素个数小于4if (nums.size() < 4)return ret;for (int a = 0; a < nums.size() - 3;) // 固定数 a{for (int b = a + 1; b < nums.size() - 2;) // 固定数 b{        // 1.2 特殊情况  数据溢出long long my_target = (long long)target - nums[a] - nums[b];int left = b + 1, right = nums.size() - 1;while (left < right){int sum = nums[left] + nums[right];if (sum > my_target)right--;else if (sum < my_target)left++;else{ret.push_back({ nums[a],nums[b],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--;}}// 去重 bb++;while (b < nums.size() && nums[b] == nums[b - 1])b++;}// 去重 aa++;while (a < nums.size() && nums[a] == nums[a - 1])a++;}return ret;}
};

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

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

相关文章

Python 学习之基础语法(一)

Python的语法基础主要包括以下几个方面&#xff0c;下面将逐一进行分点表示和归纳&#xff1a; 一、基本语法 1. 注释 a. 单行注释&#xff1a;使用#开头&#xff0c;例如# 这是一个单行注释。 b. 多行注释&#xff1a;使用三引号&#xff08;可以是三个单引号或三个双引号&…

MySQL高级-SQL优化- order by 优化(尽量使用覆盖索引、注意联合索引创建的规则、增大排序缓冲区大小)

文章目录 0、order by优化原则1、Using filesort2、Using index3、连接数据库4、查看索引5、删除索引6、按照年龄进行排序7、执行计划 order by age8、执行计划 order by age,phone9、创建联合索引 (age,phone)10、再次执行计划 order by age11、再次执行计划 order by age,pho…

013、MongoDB常用操作命令与高级特性深度解析

目录 MongoDB常用操作命令与高级特性深度解析 1. 数据库操作的深入探讨 1.1 数据库管理 1.1.1 数据库统计信息 1.1.2 数据库修复 1.1.3 数据库用户管理 1.2 数据库事务 2. 集合操作的高级特性 2.1 固定集合(Capped Collections) 2.2 集合验证(Schema Validation) 2.…

基于go1.19的站点模板爬虫

一、go1.19 go1.19是Go语言的一个版本,于2021年8月发布。它带来了许多新的功能和改进,包括但不限于以下方面: 并发性能改进:go1.19引入了新的调度器算法,称为“网状调度器(netlink scheduler)”,它可以更好地处理大量并发任务,在某些情况下提高了系统的并发能力。 垃…

计算机高并发浅析

一、 高并发简介 高并发应用场景涉及大量用户同时访问或操作系统&#xff0c;这对系统的性能、稳定性和扩展性提出了高要求。以下是一些常见的高并发应用场景及其复杂性简介&#xff1a; 1. 电商平台 场景&#xff1a;在大促销活动期间&#xff0c;如双十一、黑色星期五等&a…

标准版小程序订单中心path审核不通过处理教程

首先看自己小程序是不是已经审核通过并上线状态才在站内信里面提醒的&#xff1f; 如果没有提交过审核&#xff0c;请在提交的时候填写。path地址为&#xff1a;pages/goods/order_list/index 如果是已经上线的小程序&#xff0c;当时没要求填这个&#xff0c;但新的政策要求填…

聊天伴侣-豆包

前言 2024年5月14日凌晨&#xff0c;OpenAI发布最新多模态大模型 GPT-4o。GPT-4o的“o”代表“omni”&#xff0c;意为全能&#xff0c;与现有模型相比&#xff0c;它在视觉和音频理解方面尤其出色。GPT-4o可以在音频、视觉和文本中进行实时推理&#xff0c;接受文本、音频和图…

队列的相关知识

目录 创建 初始化 销毁 头插 尾删 取出头 取出尾 数字个数 判空 队列的性质与特征 性质&#xff1a;一种先进先出的线性表 特征&#xff1a;FIFO&#xff08;先进先出&#xff09; 实现&#xff1a;用数组和链表的都可以 例子&#xff1a;在生产者消费者模型用到了…

夏天到了,用这两款软件,悄悄惊艳所有人!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 夏天来了&#xff0c;又到了“露肉”的季节&#xff0c;或许大家会为了身材烦恼&#xff0c;即便有运动意愿却苦于健身计划和时间上安排&#xff0c;也没有合适的免费软件。 别担心&a…

RpcRrovider分发rpc服务(OnMessage和Closure回调)

目录 1.完善rpcprovider.cc的OnConnection 2.完善rpcprovider.cc的OnMessage 3.完整rpcprovider.h 4.完整rpcprovider.cc 这篇文章主要完成&#xff0c;protobuf实现的数据序列化和反序列化。 1.完善rpcprovider.cc的OnConnection rpc的请求是短连接的&#xff0c;请求一次…

CICD持续集成(Jenkins+Git+Gogs)

1.Jenkins Jenkins 是一个开源的、用于构建和自动化软件开发流程的持续集成和交付工具。它提供了一个可扩展的平台&#xff0c;用于构建、测试和部署软件项目。通过使用 Jenkins&#xff0c;开发团队可以实现持续集成和交付&#xff0c;自动化构建和测试过程&#xff0c;提高软…

Web缓存代理和CDN 内容分发网络

目录 1.WEB缓存代理 1.1 WEB缓存代理作用 1.2 常见WEB缓存代理 1.3 Nginx 配置 缓存代理 2. CDN内容分发网络 1.WEB缓存代理 1.1 WEB缓存代理作用 存储一些之前给访问过的&#xff0c;且可能要被再次访问的静态网页资源对象&#xff0c;使客户端可以直接从缓存代理服务器…

【代码随想录训练营】【Day 60】【动态规划-13】| Leetcode 647, 516

【代码随想录训练营】【Day 60】【动态规划-13】| Leetcode 647, 516 需强化知识点 动态规划-回文系列 题目 647. 回文子串 注意sum&#xff08;dp&#xff09;不行j的遍历要倒序&#xff0c;并且 for j in range(i, n): class Solution:def countSubstrings(self, s: st…

C++Primer Plus 第十四章代码重用:14.4.7 成员模板

CPrimer Plus 第十四章代码重用 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;CPrimer Plus 第十四章代码重用&#xff1a;14.4.7 成员模板 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如…

KBL410-ASEMI智能AI专用整流桥KBL410

编辑&#xff1a;ll KBL410-ASEMI智能AI专用整流桥KBL410 型号&#xff1a;KBL410 品牌&#xff1a;ASEMI 封装&#xff1a;KBL-4 正向电流&#xff08;Id&#xff09;&#xff1a;4A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;2…

【计算机毕业设计】基于微信小程序的电子购物系统的设计与实现【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

Python逻辑控制语句 之 判断语句--if语句的基本结构

1.程序执行的三大流程 顺序 分支&#xff08;判断&#xff09; 循环 2.if 语句的介绍 单独的 if 语句,就是 “如果 条件成⽴,做什么事” 3.if 语句的语法 if 判断条件: 判断条件成立&#xff0c;执行的代码…

Python转换图片为BITMAP供OLED屏幕显示

最近在玩ESP32&#xff0c;外接了一个0.96寸的oled屏幕&#xff0c;不想找取模软件了&#xff0c;直接gpt生成代码&#xff0c;小改一下直接用了。 字体下载地址&#xff1a;https://fonts.google.com/selection?queryNotoSans from PIL import Image, ImageDraw, ImageFont…

防止多次点击,vue的按钮上做简易的防抖节流处理

话不多说,上个视频,看看是不是你要的效果 防抖节流 1.创建一个directive.js // directive.js export default {install(Vue) {// 防重复点击(指令实现)Vue.directive(repeatClick, {inserted(el, binding) {el.addEventListener(click, () > {if (!el.disabled) {el.disabl…

Leetcode 450:删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#xff1a; 首先…