与双指针的亲密接触:快与慢的浪漫交错

news2024/10/19 13:46:19

在这里插入图片描述

公主请阅

  • 1.合并两个有序数组
    • 1.1 题目说明
      • 示例 1
      • 示例 2
      • 示例 3
    • 1.2 题目分析
    • 1.3代码部分
    • 1.4 代码解析
  • 2.移动零
    • 2.1题目说明
      • 示例 1
      • 示例 2
    • 2.2题目分析
    • 2.3代码部分
    • 2.4代码解析

1.合并两个有序数组

在这里插入图片描述
题目传送门

1.1 题目说明

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 mn,分别表示 nums1nums2 中的元素数目。

请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意
最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0,应忽略。nums2 的长度为 n


示例 1

输入

  • nums1 = [1, 2, 3, 0, 0, 0]
  • m = 3
  • nums2 = [2, 5, 6]
  • n = 3

输出[1, 2, 2, 3, 5, 6]

解释:需要合并 [1, 2, 3][2, 5, 6]。合并结果是 [1, 2, 2, 3, 5, 6],其中斜体加粗标注的是 nums1 中的元素。


示例 2

输入

  • nums1 = [1]
  • m = 1
  • nums2 = []
  • n = 0

输出[1]

解释:需要合并 [1][]。合并结果是 [1]


示例 3

输入

  • nums1 = [0]
  • m = 0
  • nums2 = [1]
  • n = 1

输出[1]

解释:需要合并的数组是 [][1]。合并结果是 [1]。注意,因为 m = 0,所以 nums1 中没有元素,nums1 中仅存的 0 仅是为了确保合并结果可以顺利存放到 nums1 中。


1.2 题目分析

题目让我们合并两个非递减顺序排列的整数数组nums1nums2,此外还有两个整数mn分别表示nums1nums2中的元素的个数,但是我们的nums1的初始长度是m+nnums2的初始化长度是n,说白了就是直接将nums2中的数据挪到nums1中去,然后在挪动的过程中进行排序的操作

那么对于这种题型,出现了两个数组,那么我们是否能使用双指针算法呢?
那么这里说说我的思路哈:

  • 先定义两个指针,一个指向nums1的有效数据的尾部(即m-1),另外一个指针指向nums2的末尾(即n-1)
  • 我们从nums1的最后一个位置开始进行元素的填充,即从m+n-1这个位置开始
  • 我们依次比较nums1nums2中当前指针指向的元素,将其中较大的元素放到nums1的后面的位置
  • 不断地进行两个指针的移动操作,直到其中一个数组的所有元素都被处理完了
  • 如果nums2中还存在剩余的元素的话,我们直接将nums2中剩下的部分赋值到nums1中,(这个时候的nums1本身的前面就是已经有序了)

那么思路成立,下面就是我们的代码部分了

1.3代码部分


//nums1的初始长度就是m+n
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
  int p1=m-1;//nums1最后一个有效元素的下标
  int p2=n-1;//nums2最后一个有效元素的下标
  int p=m+n-1;//这个是nums1的总长度的末尾

  //从后往前进行合并操作
  while(p1>=0&&p2>=0)//循环停止的条件,只要两个数组中都存在未处理的元素的话,就可以继续进行合并的执行操作
  {
      //因为给我们的nums1和nums2都是递减的数组,是有序的
      

      //每次比较的时候将两组中大的元素放到p的位置
      if(nums1[p1]>nums2[p2])
      {
          nums1[p]=nums1[p1];
          p1--;
      }
      else
      {
          nums1[p]=nums2[p2];
          p2--;
      }
      p--;//放下一个元素,这里是换位置
  }
  //到这里的话肯定nums1的指针已经是出界了,不满足循环条件了,但是现在nums2hiatus有元素存在的,那么我们就直接将nums2中剩下的的元素直接复制到nums1中
  while(p2>=0)
  {
      nums1[p]=nums2[p2];
      p2--;
      p--;
  }
}

1.4 代码解析

我们先设置好下标为指向位置,就依照我们的这个题的思路那里进行下标设置
然后我们使用这个while循环进行操作
这个while循环的条件是只要我们的两个指针是大于等于0的话就一直进行循环操作,直到出现合并的现象或者是有一个数组的下标变成0了,然后另外一个数组还有元素没有完成迁移

在循环中,我们利用两个下标进行比较的操作
两个数组中元素大的那一个放到nums1的后面
放完之后我们将迁移元素的那个数组的指针往左边移动一位,操作就是指针减减
对于上面的操作存在两种情况,一种是nums1中的那个指针指向的元素大,另一种就是nums2中的元素大了。
进行完上述的操作之后,我们已经让一个元素放到了nums1的末尾了
那么这个末尾的指针就需要向坐进行移动一步的操作了

然后我们出循环
到这里的话就是两种情况,一种就是nums1nums2合并完成了,还有一种就是nums1的指针小于0了,因为nums1里面的元素已经移动完了,那么此时就是nums2中还存在元素没有进行迁移了
那么我们直接将nums2中剩下的元素放到nums1里面就行了,因为此时nums2中的元素都是比nums1小的元素了

2.移动零

在这里插入图片描述

题目传送门

2.1题目说明

给定一个数组 nums,编写一个函数将所有的 0 移动到数组的末尾,同时保持非零元素的相对顺序。

注意
必须在不复制数组的情况下原地对数组进行操作。


示例 1

输入nums = [0, 1, 0, 3, 12]
输出[1, 3, 12, 0, 0]


示例 2

输入nums = [0]
输出[0]


2.2题目分析

这类题可以分为数组划分或者叫做数组分块

解决这类题我们首先就想到了双指针算法

这里的指针是利用数组下标来充当指针

因为在数组中我们可以利用下标索引到对应的元素

我们定义的两个指针一个是dest 一个是cur

两个指针的作用

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

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

cur在扫描后会将数组分为两个区间,一个是左边,一个是右边,右边就是待处理的区间,左边就是处理过的

然后再cur处理过的左区间,我们的dest在里面又区分了两个区间,左边的就是非0元素,右边的就是0

所以上面会说dest是已处理的区间内,非0元素的最后一个位置

所以这两个指针将整个数组划分为三个部分

在这里插入图片描述
三个区间:

[0,dest] [dest+1,cur-1] [cur,n-1]

非0元素 0 待处理

一开始我们让cur指向第一个元素,因为一开始我们没有开始扫描没有非0元素,所以让dest先指向-1下标这个元素

我们先让cur进行从左往右的扫描操作

当我们的cur遇到0元素的时候cur直接向后移动一位就行了

如果我们的cur碰到非0元素的话

先让dest++,然后让cur位置和dest位置的元素进行交换的操作

如何做到cur从前往后遍历的过程中

2.3代码部分

class Solution {
public:
    void moveZeroes(vector<int>& nums)
    {
        for(int cur=0,dest=-1;cur<nums.size();cur++)
        {
            if(nums[cur])//当cur指向的数不等于0的话
            swap(nums[++dest],nums[cur]);//让dest自增1,增完之后正是我想要交换的
        }
    }
};

2.4代码解析

如何做到cur从前往后遍历的过程中

1.遇到0元素:cur++

2.遇到非0元素:swap(dest+1,cur)

dest++,cur++

我们在这个函数里面写入一个for循环,然后循环的条件就是直到cur走完这个数组就结束,那么只要这个cur的大小小于这个数组的元素我们就能进行循环操作
通过cur遍历整个数组,只要我们的cur指向的元素不是0的话,我们就进行条件语句,先将dest进行++操作,然后我们将dest指向的元素和cur指向的元素进行交换的操作然后这么0就到后面去了,非0元素就在前面了

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

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

相关文章

25计软新增考研院校!或可捡漏上岸!

C哥专业提供——计软考研院校选择分析专业课备考指南规划 新增的计算机与软件工程考研院校为考研同学带来了多方面的机遇&#xff0c;这些机遇不仅体现在过国家线后可能面临的更低竞争压力&#xff0c;还包括更多元化的教育选择和更广阔的就业前景&#xff1a; 一、降低竞争压…

周报5<仅供自己学习>

文章目录 一、NeRF代码1.齐次化位姿坐标2.理解rays_d和rays_o3.min_line_dist的函数问题1&#xff1a;该函数的作用问题2&#xff1a;为何要计算ray_d的外积①形成投影矩阵&#xff08;1&#xff09;投影矩阵&#xff08;2&#xff09;投影矩阵的性质&#xff08;3&#xff09;…

网络编程基础-IO模型深入理解

一、IO的基本概念 什么是IO&#xff1f; I/O就是计算机内存与外部设备之间拷贝数据的过程 什么是网络IO&#xff1f; 网络IO是指在计算机网络环境中进行的输入和输出操作&#xff0c;涉及数据在网络设备之间的传输。 网络IO操作可以是发送请求、接收响应、下载文件、传输数…

adb devices没找到安卓设备的解决办法

要想让设备让adb识别到&#xff0c;要开启设备的开发者模式&#xff0c;并且开启USB调试功能&#xff1a; 然后重新运行&#xff1a;就找到了

Linux零基础教程学习(黑马)

1.初识Linux 1.2远程连接Linux系统 图形化、命令行 对于操作系统的使用&#xff0c;有2种使用形式&#xff1a; 图形化页面使用操作系统 以命令的形式使用操作系统 不论是Windows还是Linux亦或是MacOS系统&#xff0c;都是支持这两种使用形式。 图形化&#xff1a;使用操作…

前端页面使用google地图api实现导航功能,开发国外网站免费简单好用

开发国外软件的时候&#xff0c;想使用goole map实现导航等功能&#xff0c;可以使用google的api来做&#xff0c;官方文档地址&#xff1a;https://developers.google.com/maps/documentation/urls/get-started?hlzh-cn &#xff0c;比如&#xff1a; 支持的请求的操作&…

基于MATLAB/octave的容积卡尔曼滤波(CKF)【带逐行注释】

介绍 CKF的三维滤波程序例程 产品概述 我们的 MATLAB 数据处理工具是专为科研人员、工程师和数据分析师设计的高效解决方案。该工具提供了一系列强大的功能&#xff0c;能够快速处理和分析大规模数据集&#xff0c;适用于各种科学和工程应用&#xff0c;包括信号处理、图像分…

Redis Search系列 - 第四讲 支持中文

目录 一、支持中文二、自定义中文词典2.1 Redis Search设置FRISOINI参数2.2 friso.ini文件相关配置1&#xff09;自定义friso UTF-8字典2&#xff09;修改friso.ini配置文件 三、实测中文分词效果 一、支持中文 Redis Stack 从版本 0.99.0 开始支持中文文档的添加和分词。中文…

什么是大数据分析:定义、优缺点、应用、机遇和风险

大数据分析的概念已经成为我们社会不可或缺的一部分。众多公司和机构已经开发了大数据应用程序&#xff0c;取得了不同程度的成功。社交媒体平台和传感器等技术正在以前所未有的速度生成数据&#xff0c;就像一条装配线。如今&#xff0c;几乎所有东西都是物联网的一部分&#…

C#教程笔记

C#开发的程序依附.NET平台 编译器->IL中间语言->CLR->机器指令 .NET CORE平台 跨平台 .cs后缀名 快捷键 CtrlKD格式化CtrlL或CtrlX删除一行CtrlY反撤销cwTab快速生成命令行输出Ctrl空格或CtrlJ获取提示///方法注释CtrlMO代码全部折叠CtrlML代码全部展开 上升沿0变1 安…

硬件产品经理的开店冒险之旅(下篇)

缘起&#xff1a;自己为何想要去寻找职业第二曲线 承接上篇的内容&#xff0c;一名工作13年的普通硬件产品经理将尝试探索第二职业曲线。根本原因不是出于什么高大上的人生追求或者什么职业理想主义&#xff0c;就是限于目前的整体就业形式到了40岁的IT从业人员基本不可能在岗…

Spring Boot技术栈在电影评论网站中的应用

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【论文阅读】Bi-Mamba+: Bidirectional Mamba for Time Series Forecasting

文章目录 概要阅读背景知识引言创新之处 研究方法概述方法部分的核心模块多尺度打补丁&#xff08;Multi-Scale Patching&#xff09;Mamba&#xff1a;全局模式专家Local Window Transformer&#xff08;LWT&#xff09;&#xff1a;局部变化专家长短期路由器&#xff08;Long…

Aatrox-Bert-VITS2部署指南

一、模型介绍 【AI 剑魔 ①】在线语音合成&#xff08;Bert-Vits2&#xff09;&#xff0c;将输入文字转化成暗裔剑魔亚托克斯音色的音频输出。 作者&#xff1a;Xz 乔希 https://space.bilibili.com/5859321 声音归属&#xff1a;Riot Games《英雄联盟》暗裔剑魔亚托克斯 …

LLM:参数高效微调方法总结

可以分为基于适配器、基于提示的。 一、基于适配器的方法 其核心思想是在预训练模型的各层之间插入轻量级的额外模块——适配器&#xff0c;通过仅微调这些适配器模块以适应特定的下游任务&#xff0c;同时冻结原模型的大部分参数。 1.Lora系列 原始的Lora LoRA 表示通过低…

DFS算法经典题目: Leetcode 51.N皇后

DFS算法经典题目&#xff1a; Leetcode 51.N皇后 题目详情如下 这道题如果使用暴力解法的话&#xff0c;需要对N个皇后放在每个地方都进行枚举并判断是否可行&#xff0c;时间复杂度非常之高&#xff0c;肯定是过不了的&#xff0c;所以需要使用其他解法。 根据题目可以知道每…

RT-Thread之STM32使用定时器实现输入捕获

前言 基于RT-Thread的STM32开发&#xff0c;配置使用定时器实现输入捕获。 比如配置特定通道捕获上升沿&#xff0c;该通道对应的引脚有上升沿信号输入&#xff0c;则触发捕获中断。 一、新建工程 二、工程配置 1、打开CubeMX 进行工程配置 2、时钟使用外部高速晶振 3、配置…

链栈的基本算法

初始化一个链栈 &#xff0c;将元素e&#xff0c;f&#xff0c;g&#xff0c;h&#xff0c;i依次进栈&#xff0c;获取栈顶元素&#xff0c;将栈中元素依次出栈并输出 链栈的表示 既采用链式储存结构实现的栈 具体代码 #include <stdio.h> #include <stdlib.h>…

安装TDengine数据库3.3版本和TDengine数据库可视化管理工具

安装TDengine数据库3.3版本和TDengine数据库可视化管理工具 一、下载安装包二、解压安装包三、部署四、启动服务五、进入数据库六、创建数据库、表和往表中插入数据七、测试 TDengine 性能八、使用数据库九、查询数据十、TDengine数据库可视化界面 一、下载安装包 TDengine-cl…

RHCE——例行性工作

准备工作 [rootlocalhost ~]# cat /etc/yum.repos.d/aliyun.repo [ali-app] nameali-app baseurlhttps://mirrors.aliyun.com/centos-stream/9-stream/AppStream/x86_64/os/ gpgcheck0[ali-base] nameali-base baseurlhttps://mirrors.aliyun.com/centos-stream/9-stream/Base…