【算法一周目】双指针(1)

目录

1.双指针介绍

2.移动零

解题思路

 C++代码实现

3.复写零

解题思路

C++代码实现

4.快乐数

解题思路

C++代码实现

5.盛水最多的容器

解题思路

C++代码实现


1.双指针介绍

常见的双指针有两种形式,一种是对撞指针,一种是快慢指针。

对撞指针:一般用于顺序结构中,也称左右指针。

  • 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。
  • 对撞指针的终止条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环),也就是:

left == right (两个指针指向同⼀个位置);
left > right (两个指针错开);

快慢指针:又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针数组或链表等序列结构上移动。

这种方法对于处理环形链表或数组非常有用。其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。

快慢指针的实现方式有很多种,最常用的一种是:一次循环中,每次让慢指针向后移动一位,而快的指针向后移动两位,实现一快一慢。

2.移动零

题目链接:283. 移动零
题目描述:给定一个数组nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

解题思路

这题我们使用双指针解决,需要一个cur指针和一个dest指针,将数组划分成3个区间,[0, dest]的元素全部是非0元素[dest + 1, cur - 1]的元素全是0[cur -1, n - 1]的元素是待处理的

具体流程如下:

1.初始化cur = 0(用于遍历数组),dest = -1(指向非0元素的最后一个位置,由于刚开始我们不知道最后一个非0元素在什么位置,因此初始化为-1

2.cur依次往后遍历每个元素。

  • 当cur遇到0时,cur++
  • 当cur遇到非0时,dest++,交换dest的位置与cur位置的值

 C++代码实现

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

时间复杂度:O(n)

空间复杂度:O(1)

3.复写零

题目链接:1089. 复写零
题目描述:给定一个固定长度的整数数组arr,在遇到每个零时,将其右移并插入一个零,同时保持数组长度不变。

解题思路

因为数组的0需要复写2次有可能会把后面的非0元素覆盖掉,所以从前往后复写是不可取的,所以我们采取从后往前复写。

具体过程如下:

1.找到最后一个需要复写的元素,这一步需要双指针来解决。

  • 初始化两个指针cur = 0, dest = -1
  • cur的位置为0时,dest += 2非0时dest++
  • 判断dest是否大于等于n - 1(数组最后一个位置),若满足则退出循环
  • cur++,继续循环,直到找到最后一个复写的元素。

2.处理越界情况,当dest == n时,说明cur在数组n - 2位置且元素是0,这时候就要特殊处理,dest--,将arr[dest]置0,dest--,cur--。

3.从后往前复写将arr[cur]复写到arr[dest]若arr[cur]为非0,复写一次,若arr[cur]为0,则复写两次,记得分情况更新cur和dest,直到复写结束。

C++代码实现

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

时间复杂度:O(n)

空间复杂度:O(1)

4.快乐数

题目链接:202. 快乐数

题目描述:编写一个算法来判断一个数 n 是不是快乐数。

对于n = 2,2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16,进入到循环了。

解题思路

为了方便分析,将“对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和”这一操作记为f操作

由题目可知,当我们对一个数不断进行f操作时,最后一定会进入死循环死循环也分为两种第一种就是一直在1循环,是快乐数第二种就是在历史数据中死循环,但始终变不到1。

由于两种情况只会出现一种,所以我们只需判断是否一直在1循环,就可知此数是不是快乐数。

证明

  • 对于INT_MAX(2^31-1=2147483647),取一个更大的数9999999999,进行f操作后得到最大值810,可以得到f操作得到的值范围是[1, 810]
  • 根据“鸽巢原理”,对一个数进行f操作811次后,必定进入循环。

对此,我们可以得知,无论是什么数,对其进行多次f操作后,必定会形成一个环,所以我们可以使用快慢指针来解决。

具体过程:

1.编写f操作的函数bitsum,将该数替换为它每个位置上的数字的平方和。

2 .初始化快慢指针,slow = n,fast = bitsum(n)

3.当slow != fast时slow向前走一步,fast先前走两步,直到循环结束。

4.判断slow是否等于1,若等于则该数是快乐数。

C++代码实现

class Solution {
public:int bitsum(int n){int ret = 0;while(n){ret += pow(n % 10, 2);n /= 10;}return ret;}bool isHappy(int n) {int slow = n, fast = bitsum(n);while(slow != fast){slow = bitsum(slow);fast = bitsum(bitsum(fast));}return slow == 1;}
};

时间复杂度:O(log n) 在快慢指针法中,求平方和的时间复杂度为对数级别。

空间复杂度:O(1)

5.盛水最多的容器

题目链接:11. 盛最多水的容器

题目描述:给定一个长度为n的整数数组height,有n条垂线,第i条线的两个端点是(i, 0) 和(i, height[i])。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1

  • 输入:[1,8,6,2,5,4,8,3,7]
  • 输出:49
  • 解释:数组中的垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在这个情况下,能够容纳水(表示为蓝色部分)的最大值是49。

解题思路

对于该题,我们很容易就想到使用暴力解法,用两个for循环暴力枚举能构成的所有容器找出其中容积最大的值。

容器计算公式:设两个指针i,j,分别指向容器的最左端和最右端,此时容器的宽度为j - 1,由于容器的高度由较短的高度决定,可得容器公式。

v = (j - i) * min(height[i], height[j])

暴力解法的代码

class Solution {
public:int maxArea(vector<int>& height) {int n = height.size();int ret = 0;// 两层 for 循环枚举出所有可能出现的情况for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {// 计算容积,找出最大的那一个ret = max(ret, min(height[i], height[j]) * (j - i));}}return ret;}
};

但是暴力解法需要遍历所有可能的组合,故时间复杂度是O(n ^ 2),如果提交到leetcode上是会超时,所以我们要寻求最优的解法。

利用双指针来解决,具体过程如下:

1.使用两个指针left和right分别指向容器的左右两个端点,初始化left = 0, right = n - 1。

2.通过左边界height[leftt]右边界height[right]计算出容器的体积v

3.判断左右边界的大小情况,舍去小的边界,若左边界 < 右边界left++反之则right--

4.通过重复上述过程,可以舍去大量不必要的枚举过程直到left与right相遇,整个过程中更新出容器体积的最大值。

证明以上的第三点,为什么不用小的边界去枚举剩下的数,而是直接将其舍去

C++代码实现

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

时间复杂度:O(n)

空间复杂度:O(1)


拜拜,下期再见😏

摸鱼ing😴✨🎞

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

6547网:青少年软件编程Python等级考试(六级)真题试卷

2024年9月青少年软件编程Python等级考试&#xff08;六级&#xff09;真题试卷 题目总数&#xff1a;38 总分数&#xff1a;100 选择题 第 1 题 单选题 下面Python代码运行后出现的图像是&#xff1f;&#xff08; &#xff09; import matplotlib.pyplot as plt im…

【5种灵活有效方式】如何从死机手机中恢复内部数据?

本文介绍了5种方法来从死机的Android设备中恢复数据&#xff0c;包括使用U1tData安卓数据恢复软件、SD卡、OTG、Google云端硬盘和SamsungCloud。这些方法覆盖了不同情况下的数据恢复需求。 摘要由CSDN通过智能技术生成 我的手机掉在地上&#xff0c;现在无法开机。我丢失了所…

【安全测试】sqlmap工具(sql注入)学习

前言&#xff1a;sqimap是一个开源的渗透测试工具&#xff0c;它可以自动化检测和利用SQL注入缺陷以及接管数据库服务器的过程。它有一个强大的检测引擎&#xff0c;许多适合于终极渗透测试的小众特性和广泛的开关&#xff0c;从数据库指纹、从数据库获 取数据到访问底层文件系…

行业类别-智慧城市-子类别智能交通-细分类别自动驾驶技术-应用场景城市公共交通优化

1.大纲分析 针对题目“8.0 行业类别-智慧城市-子类别智能交通-细分类别自动驾驶技术-应用场景城市公共交通优化”的大纲分析&#xff0c;可以从以下几个方面进行展开&#xff1a; 一、引言 简述智慧城市的概念及其重要性。强调智能交通在智慧城市中的核心地位。引出自动驾驶…

24.11.11 JavaScript1

JavaScript&#xff08;简称js&#xff09;是⼀种描述语⾔&#xff0c;基于对象和事件驱动的脚本语⾔ JavaScript特点:脚本语⾔&#xff08;⼀种轻量级的编程语⾔&#xff09; ⼀种解释性语⾔&#xff08;⽆需预编译&#xff09; 被设计为向HTML⻚⾯添加交互⾏为 运⾏于客户端&…

PDF24:多功能 PDF 工具使用指南

PDF24&#xff1a;多功能 PDF 工具使用指南 在日常工作和学习中&#xff0c;PDF 是一种常见且重要的文档格式。无论是查看、编辑、合并&#xff0c;还是转换 PDF 文件&#xff0c;能够快速高效地处理 PDF 文档对于提高工作效率至关重要。PDF24 是一款免费、功能全面的 PDF 工具…

计算机的错误计算(一百五十一)

摘要 探讨 MATLAB 中反正弦 asin 与反余弦 acos 函数的计算精度问题。 例1. 已知 计算 及 直接贴图吧&#xff1a; 另外&#xff0c;16位的正确值分别为 0.1570785896071048e1、0.1043072384837152e-4、-0.1570785896071048e1 与 0.3141582222865945e1&#xff08;I…

Lua进阶用法之Lua和C的接口设计

一&#xff1a;lua/c的接口编程 首先skynet、openresty 都是深度使用 lua 语言的典范&#xff1b;学习 lua 不仅仅要学习基本用法&#xff0c;还要学会使用 c 与 lua 交互&#xff0c;这样才学会了 lua 作为胶水语言的精髓&#xff0c;下面看一下他们两个的调用过程。 虚拟栈&a…

macOS 下的 ARM 裸机嵌入式开发入门- 第二部分:实现第一个裸机应用并且调试

1、准备二进制运行程序镜像 利用 QEMU 仿真一个完整的系统&#xff0c;并创建最简单的“Hello world!”示例。 QEMU 模拟器支持 VersatilePB 平台&#xff0c;该平台包含一个 ARM926EJ-S 核心&#xff0c;以及其他外设&#xff0c;四个 UART 串行端口&#xff1b;特别是第一个…

【网络面试篇】其他面试题——Cookie、Session、DNS、CDN、SSL/TLS、加密概念

目录 一、HTTP 相关问题 1. Cookie 和 Session 是什么&#xff1f; &#xff08;1&#xff09;Cookie &#xff08;2&#xff09;Session 2. Cookie 的工作原理&#xff1f; 3. Session 的工作原理&#xff1f; 4. Cookie 和 Session 有什么区别&#xff1f; 二、其他问…

【数值分析】复习1---牛顿迭代法

首先&#xff0c;我们先来回顾一下牛顿迭代法的概念。 这里注意的是&#xff0c;牛顿迭代法是一种线性方法&#xff0c;它在点 x k x_k xk​处进行线性展开&#xff0c;而且展开成一阶泰勒公式&#xff01;注意是一阶&#xff0c;不是二阶&#xff0c;不是更高阶&#xff0c;所…

文本语义分块、RAG 系统的分块难题:小型语言模型如何找到最佳断点

文本语义分块、RAG 系统的分块难题&#xff1a;小型语言模型如何找到最佳断点&#xff1f; 转自jina最新的关于文本语义分块的分享和模型 之前我们聊过RAG 里文档分块 (Chunking) 的挑战&#xff0c;也介绍了 迟分 (Late Chunking) 的概念&#xff0c;它可以在向量化的时候减…

PostgreSQL中如果有Left Join的时候索引怎么加

在PostgreSQL中&#xff0c;当你的查询包含多个LEFT JOIN和WHERE条件时&#xff0c;合理地添加索引可以显著提高查询性能。以下是一些具体的优化步骤和建议&#xff1a; 1. 分析查询 使用 EXPLAIN ANALYZE 命令分析你的查询&#xff0c;了解查询的执行计划&#xff0c;识别出连…

温度虽寒,其道犹变:OpenAI接口之温度参数设置为0,为何每次回复仍有不确定性?

问题描述 调用openai API&#xff0c;使用templature 0&#xff0c;每次返回的内容仍有一些不同 >>> client OpenAI( ... api_keyapi_key, ... base_urlapi_base) #第一次尝试 >>> response client.chat.completions.create(mo…

vue-h5:在h5中实现相机拍照加上身份证人相框和国徽框

参考&#xff1a; https://blog.csdn.net/weixin_45148022/article/details/135696629 https://juejin.cn/post/7327353533618978842?searchId20241101133433B2BB37A081FD6A02DA60 https://www.freesion.com/article/67641324321/ https://github.com/AlexKratky/vue-camer…

国标GB28181视频平台EasyCVR私有化部署视频平台对接监控录像机NVR时,录像机“资源不足”是什么原因?

EasyCVR视频融合云平台&#xff0c;是TSINGSEE青犀视频“云边端”架构体系中的“云平台”系列之一&#xff0c;是一款针对大中型项目设计的跨区域、网络化、视频监控综合管理系统平台&#xff0c;通过接入视频监控设备及视频平台&#xff0c;实现视频数据的集中汇聚、融合管理、…

【Android、IOS、Flutter、鸿蒙、ReactNative 】标题栏

Android 标题栏 参考 Android Studio版本 配置gradle镜像 阿里云 Android使用 android:theme 显示标题栏 添加依赖 dependencies {implementation("androidx.appcompat:appcompat:1.6.1")implementation("com.google.android.material:material:1.9.0")…

歌尔微拟赴港IPO,揭示AI+终端升级的供给革命

1959年&#xff0c;美国物理学家理查德费曼在他著名的演讲“底部有足够的空间”中&#xff0c;首次提出了将机器小型化到原子和分子尺度的想法。这个充满想象力的观点&#xff0c;为世界科技发展开启了一扇新的窗口。 时至今日&#xff0c;应这一理念而生的MEMS产品已经成为各…

ROS第七梯:ROS+VSCode+Python环境配置

第一步:Python版本的ROS项目和C++版本的ROS项目前期创建功能包的步骤基本一致,具体可参考第二章。 第二步:在功能包的目录下创建一个与src目录平级的文件夹,名称写作scripts: 第三步:在scripts文件夹下创建python的节点代码文件,此处以一个订阅节点代码文件为例:

洛谷解题日记||基础篇3

#include <iostream> #include <iomanip> // 用于设置输出格式 using namespace std;double a, b, c, d;// 定义方程 f(x) ax^3 bx^2 cx d double fc(double x) {return a * x * x * x b * x * x c * x d; }int main() {double l, r, m, x1, x2;int s 0;/…