Leetcode双指针法应用

1.双指针法

文章目录

    • 1.双指针法
      • 1.1什么是双指针法?
      • 1.2解题思路
      • 1.3扩展

1.1什么是双指针法?

双指针算法是一种在数组或序列上操作的技巧,实际上是对暴力枚举算法的一种优化,通常涉及到两个索引(或指针)从两端或从某个特定起点开始向中间靠拢,以解决特定问题。这种算法在处理数组中的元素对、查找、排序和去除重复元素等问题上特别有效。

  • 初始化:设定两个指针,它们可以同时从序列的两端开始,也可以从同一端以不同速度移动。
  • 移动规则:根据问题需求定义指针如何移动。比如,在排序数组中查找一对数之和,一个指针可以从左向右移动,另一个从右向左移动,直到两者相遇。
  • 终止条件:当指针相遇、错过彼此或是达到某种特定条件时,算法结束。

典型应用场景:

  1. 查找问题

    • 在排序数组中查找目标对:给定一个排序数组和一个目标值,找到两个数,使它们的和为目标值。如 LeetCode 的 “Two Sum II - Input array is sorted” 问题。
  2. 删除问题

    • 移除数组中的重复元素:例如,给定一个排序数组,原地删除重复出现的元素,使得每个元素最多出现两次。双指针一个用来遍历,另一个用来记录新的非重复元素的位置。
  3. 排序与翻转

    • 反转数组:可以使用双指针快速地原地反转数组的一部分或全部。两个指针一前一后交换元素直至相遇。
  4. 滑动窗口

    • 最大/最小滑动窗口:维护一个大小固定的窗口,在数组上滑动以找到窗口内的最大值或最小值,或某些统计量,如窗口内的最大和。

1.2解题思路

题目原文:

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

思路:

对于这个问题,双指针算法可以非常高效地解决。由于原始数组是非递减排序的,我们可以通过双指针从数组两端开始向中间遍历,比较两个指针所指向元素的平方值,将较大的平方值先放入结果数组中。这样可以确保结果数组始终是按非递减顺序排列的。

  1. 初始化两个指针,left指向数组的起始位置,right指向数组的末尾位置。
  2. 初始化一个空数组或列表来存放结果。
  3. left <= right时,执行以下步骤:
    • 计算leftright指针所指向元素的平方值。
    • 比较这两个平方值,将较大的那个平方值添加到结果数组的前端。
    • 移动指向较小原数值的指针。如果平方值相等,可以任选一个指针移动。
  4. left > right时,所有元素都已经处理完毕,返回结果数组。

通过这种方法,我们可以在一次遍历中完成所有计算和排序工作,时间复杂度为O(n),空间复杂度也为O(n),其中n为数组的长度。

class Solution {
public:vector<int> sortedSquares(vector<int>& nums) {vector<int>result(nums.size(),0);int left = 0;int right = nums.size() - 1;int k =  nums.size() - 1;while(left <= right){if(nums[left]*nums[left] < nums[right]*nums[right]){result[k--] = nums[right]*nums[right];right--;}else{result[k--] = nums[left]*nums[left];left++;}}return result;}
};

在这里插入图片描述

1.3扩展

题目原文:

给你两个按 非递减顺序 排列的整数数组 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 中。

思路:

双指针解题思路在这种合并有序数组的问题中非常有效。这里的关键是利用两个数组已经是非递减顺序的特点,通过两个指针分别从两个数组的末尾开始比较,并将较大的数逆序填入nums1的末尾
解题步骤:

  1. 初始化两个指针 ij,分别指向 nums1nums2 的末尾,即 i = m - 1j = n - 1。同时,设置另一个指针 k 指向 nums1 数组的最后一个有效位置,即 k = m + n - 1

  2. i >= 0j >= 0 时,进行以下操作:

    • 比较 nums1[i]nums2[j] 的值。
    • 将较大的数赋值给 nums1[k],然后对应的指针向前移动一位。如果 nums1[i] 大,则 i--;如果 nums2[j] 大或相等,则 j--
    • k--,因为每次操作都是在数组的末尾进行的。
  3. 如果 j >= 0,说明 nums2 中还有剩余元素,直接将剩余的 nums2[j] 逐个复制到 nums1 的前面,因为 nums2 的元素在 nums1 的末尾已经被正确地放置了。

class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {vector<int> arr(m + n, 0); // 创建一个足够大的临时数组int k = m + n - 1; // 初始化k为新数组的最后一个位置索引m--; // nums1的有效元素索引需要减1,因为m是原始长度n--; // nums2的同理// 注意循环条件应该是 k >= 0,因为我们要从末尾开始填充while (k >= 0) {if (n < 0) { // 如果nums2已经全部处理完了arr[k] = nums1[m];m--;} else if (m < 0) { // 如果nums1已经全部处理完了arr[k] = nums2[n];n--;} else if (nums1[m] > nums2[n]) { // 比较条件arr[k] = nums1[m];m--;} else {arr[k] = nums2[n];n--;}k--; // 移动到下一个待填充的位置}// 最后把合并的结果复制回nums1nums1.swap(arr);}
};

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

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

相关文章

springboot实现接口请求日志自动生成(日志自动埋点)

文章目录 1.作用&#xff1a;2.原理&#xff1a;3.代码&#xff1a;一.config层二. mq层 &#xff1a;三.service层&#xff1a; 4.效果图5.声明 1.作用&#xff1a; springboot接口请求日志自动生成&#xff0c;实现接口日志自动埋点生成 1.统一日志生成格式;—方便查看 2.汇…

19-4 LLM之野望 4 - 探索大模型的量化

什么是模型量化&#xff1f; 从本质上讲&#xff0c;模型量化就是为了提高效率。想象一下&#xff0c;你有一本非常厚的教科书&#xff08;就像那些老式百科全书一样&#xff09;&#xff0c;需要整天随身携带。很累吧&#xff1f;现在&#xff0c;如果你能把它缩小到一本漫画…

Postgresql导入几何数据的几种方式

postgis方式导入 1.直接使用postgis客户端方式导入 首先&#xff0c;电脑要安装postgresql和对应版本的postgis。然后通过postgis客户端软件连接到postgresql数据库。然后导入。具体详细操作如下所示&#xff1a; 第一步&#xff1a;首先要再postgis中创建数据库 Create da…

怎样在 PostgreSQL 中进行用户权限的精细管理?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中进行用户权限的精细管理&#xff1f;一、权限管理的重要性二、PostgreSQL 中的权…

Linux云计算 |【第一阶段】ENGINEER-DAY2

主要内容&#xff1a; 磁盘空间管理fdisk、parted工具、开机自动挂载、文件系统、交换空间 KVM虚拟化 实操前骤&#xff1a; 1&#xff09;添加一块硬盘&#xff08;磁盘&#xff09;&#xff0c;需要关机才能进行操作&#xff0c;点击左下角【添加硬件】 2&#xff09;选择2…

Lamp 小白菜鸟从入门到精通

前言 “LAMP包”的脚本组件中包括了CGIweb接口&#xff0c;它在90年代初期变得流行。这个技术允许网页浏览器的用户在服务器上执行一个程序&#xff0c;并且和接受静态的内容一样接受动态的内容。程序员使用脚本语言来创建这些程序因为它们能很容易有效的操作文本流&#xff0…

2.0.PyTorch神经网络基础

层和块 块&#xff08;block&#xff09;可以描述单个层、由多个层组成的组件或整个模型本身。 使用块进行抽象的一个好处是可以将一些块组合成更大的组件&#xff0c; 这一过程通常是递归的。多个层被组合成块&#xff0c;形成更大的模型&#xff1a; #层 import torch from …

LeetCode做题记录(第二天)169. 多数元素

题目&#xff1a;169. 多数元素 标签&#xff1a;数组 哈希表 分治 计数 排序 题目信息&#xff1a; 思路一&#xff1a; 在题目中出现了计数&#xff0c;那我们就可以直接考虑考虑使用哈希表 unordered_map 即遍历的时候记录每个数的出现次数&#xff0c;当出现次数大于n/…

苍穹外卖跟练项目前端localhost打不开页面启动nginx报错[alert] could not open error log file问题解决

一、安装路径为纯英文 查看自己的安装路径是否为纯英文环境&#xff0c;刚开始下载的资料包是有中文路径的&#xff0c;要将资料包中的nginx-1.20.2文件夹复制一份然后粘贴到一个新建的纯英文的目录&#xff0c;我这里装到的是 D:\Program Files\nginx-1.20.2 二、删掉logs文件…

【AI学习】关于Scaling Law的相关学习

一、苦涩的教训 首先&#xff0c;学习一段重要话语&#xff1a; The biggest lesson that can be read from 70 years of AI research is that general methods that leverage computation are ultimately the most effective, and by a large margin. 从70年的人工智能研究中…

C语言 ——— 浮点数类型 在 内存中 的 存储模式

目录 浮点数存储规则 单\双精度浮点数 存储 S、M、E 的布局 有效数字M 和 指数位E 的特殊规定 浮点数在内存中是否存储的S、M、E 浮点数存储规则 根据国际标准IEEE754&#xff08;电气和电子工程协会&#xff09;规定&#xff1a;任意一个 浮点数F的二进制 都可以表示成…

<数据集>铁轨缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;844张 标注数量(xml文件个数)&#xff1a;844 标注数量(txt文件个数)&#xff1a;844 标注类别数&#xff1a;3 标注类别名称&#xff1a;[Spalling, Squat, Wheel Burn] 序号类别名称图片数框数1Spalling3315522…

【ProtoBuf】通讯录实现(网络版)

Protobuf 还常用于通讯协议、服务端数据交换场景。那么在这个示例中&#xff0c;我们将实现一个网络版本的通讯录&#xff0c;模拟实现客户端与服务端的交互&#xff0c;通过 Protobuf 来实现各端之间的协议序列化。 需求如下&#xff1a; 客户端可以选择对通讯录进行以下操…

达梦数据库 DISQL连接数据库与执行SQL、脚本的方法

DISQL连接数据库与执行SQL、脚本的方法 1.DISQL介绍2.DISQL连接数据库的方法2.1 本地连接2.2 远程连接2.3 CONN连接 3.执行SQL、脚本的方法3.1 通过DISQL登录后在字符界面3.2 启动DISQL时运行脚本3.3 进入DISQL后&#xff0c;通过start命令运行脚本3.4 使用EDIT命令编辑脚本 1.…

【中项】系统集成项目管理工程师-第3章 信息技术服务-3.1内涵与外延与3.2原理与组成

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

OV7670寄存器读出0x00或0xFF

文章目录 问题描述原因分析解决方案 问题描述 OV7670的输出图像异常&#xff0c;怀疑寄存器没有正确配置&#xff0c;在SignalTap中观察到SIO_D在读出阶段一直为高或低 寄存器读出0x00 寄存器读出0xFF 原因分析 在确保电源、时钟和读写时序没有问题的情况下&#xff0c;有…

PCB系统学习(1)--PCB印制电路板

PCB印制电路板 1.1PCB的定义1.2PCB的层叠结构1.2.1PCB单层板1.2.2PCB双层板1.2.3PCB四层板 1.3PCB的通孔&#xff0c;盲孔&#xff0c;埋孔1.4元器件的符号与封装1.5PCB的生产过程 1.1PCB的定义 PCB(PrintedCircuitBoard)&#xff0c;中文即印制电路板&#xff0c;或印刷线路板…

Linux--多线程

今日内容 线程的结束机制&#xff1a; 1.不同与进程没有孤儿线程和僵尸线程。 2.主进程结束&#xff0c;任意生成的次线程都会结束。(因为共享的进程空间被回收了)。 3.次线程的正常结束不会影响主线程的运行。 子线程的回收策略&a…

《0基础》学习Python——第十八讲__爬虫\<1>

一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序&#xff08;通常使用Python&#xff09;&#xff0c;爬虫可以自动化地访问网页&#xff0c;解析网页内容并提取出所需的数据。爬虫可以用于各种用途&#xff0c;如搜索引擎的索引&#xff0c;数据分析和挖掘&#x…

NVIDIA 完全过渡到开源 GPU 内核模块

目录 支持的 GPU安装程序更改将包管理器与 CUDA 元包配合使用使用 runfile使用安装帮助程序脚本包管理器详细信息apt&#xff1a;基于 Ubuntu 和 Debian 的发行版dnf&#xff1a;Red Hat Enterprise Linux、Fedora、Kylin、Amazon Linux 或 Rocky Linuxzypper&#xff1a;SUSE …