双指针算法详解:原理、应用场景及代码示例

文章目录

      • 双指针算法概述
      • 主要应用场景及实现思路
        • 1. 数组排序后的两数之和
        • 2. 链表中环的检测
        • 3. 滑动窗口
        • 4. 合并两个有序数组
        • 5. 移除数组中的重复元素
      • 总结

双指针算法概述

原理
双指针算法的核心在于使用两个指针遍历数据结构,而不是单个指针。这种方法在某些情况下可以显著减少时间复杂度,特别是在处理数组和链表时。

主要应用场景及实现思路

1. 数组排序后的两数之和

应用场景

  • 在已排序的数组中查找两个数,使它们的和等于特定的目标值。
  • 适用于需要高效查找特定组合的情况。

实现思路

  • 初始化两个指针,一个指向数组的起始位置(左指针),另一个指向数组的末尾位置(右指针)。
  • 计算两个指针所指向元素的和。
  • 根据和与目标值的比较结果,调整指针位置:
    • 如果和小于目标值,移动左指针向右。
    • 如果和大于目标值,移动右指针向左。
    • 如果和等于目标值,返回指针的位置。
  • 继续调整指针位置,直到找到答案或两个指针相遇。

代码示例

def two_sum_sorted(arr, target):left, right = 0, len(arr) - 1while left < right:current_sum = arr[left] + arr[right]if current_sum == target:return [left, right]elif current_sum < target:left += 1else:right -= 1return []# 测试
arr = [1, 2, 3, 4, 6]
target = 10
print(two_sum_sorted(arr, target))  # 输出: [3, 4]
2. 链表中环的检测

应用场景

  • 判断链表中是否存在环。
  • 适用于防止无限循环和确保链表结构的正确性。

实现思路

  • 使用两个指针,一个慢指针每次前进一步,一个快指针每次前进两步。
  • 如果链表中存在环,快指针最终会追上慢指针。
  • 如果快指针到达链表末尾(即 fastfast.nextNone),则说明链表中没有环。

代码示例

class ListNode:def __init__(self, x):self.val = xself.next = Nonedef has_cycle(head):if not head or not head.next:return Falseslow = headfast = head.nextwhile fast and fast.next:if slow == fast:return Trueslow = slow.nextfast = fast.next.nextreturn False# 测试
# 创建一个带有环的链表
node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(4)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node2  # 创建环print(has_cycle(node1))  # 输出: True
3. 滑动窗口

应用场景

  • 解决字符串或数组中子串/子数组的问题。
  • 特别适用于需要找到满足某些条件的最小子数组长度或最大和等情况。

实现思路

  • 使用两个指针作为窗口的两端,根据条件调整窗口大小。
  • 当窗口满足条件时,尝试缩小窗口以寻找更优解。
  • 通过不断调整窗口的位置和大小,直到找到满足条件的最佳解。

代码示例

from collections import Counterdef min_window(s, t):need = Counter(t)missing = len(t)left, start, end = 0, 0, 0for right, char in enumerate(s):if need[char] > 0:missing -= 1need[char] -= 1if missing == 0:while left < right and need[s[left]] < 0:need[s[left]] += 1left += 1if end == 0 or right - left < end - start:start, end = left, right + 1need[s[left]] += 1missing += 1left += 1return s[start:end]# 测试
s = "ADOBECODEBANC"
t = "ABC"
print(min_window(s, t))  # 输出: "BANC"
4. 合并两个有序数组

应用场景

  • 将两个已排序的数组合并成一个新的有序数组。
  • 适用于需要高效合并多个有序数据集的情况。

实现思路

  • 分别为两个数组设置指针,从头开始比较两个数组的当前元素。
  • 将较小的元素放入结果数组中,并移动对应的指针。
  • 继续这一过程,直到其中一个数组的所有元素都被处理完毕。
  • 最后,如果还有剩余未处理的数组,则将其余部分直接复制到结果数组的末端。

代码示例

def merge_sorted_arrays(arr1, arr2):merged = []i, j = 0, 0while i < len(arr1) and j < len(arr2):if arr1[i] < arr2[j]:merged.append(arr1[i])i += 1else:merged.append(arr2[j])j += 1# 添加剩余的元素while i < len(arr1):merged.append(arr1[i])i += 1while j < len(arr2):merged.append(arr2[j])j += 1return merged# 测试
arr1 = [1, 3, 5]
arr2 = [2, 4, 6]
print(merge_sorted_arrays(arr1, arr2))  # 输出: [1, 2, 3, 4, 5, 6]
5. 移除数组中的重复元素

应用场景

  • 在非递减数组中去除重复出现的元素,使每个元素只出现一次。
  • 适用于需要高效去重的情况。

实现思路

  • 使用两个指针,一个用于追踪当前处理到的非重复元素的位置,另一个用于遍历整个数组。
  • 遍历过程中,如果发现当前元素与前一个元素不同,则将其放置在追踪指针的位置,并向前移动追踪指针。
  • 遍历结束后,追踪指针之前的数组部分就是去重后的数组。

代码示例

def remove_duplicates(arr):if not arr:return 0write_pointer = 1  # 写指针,记录下一个非重复元素的位置for read_pointer in range(1, len(arr)):if arr[read_pointer] != arr[read_pointer - 1]:arr[write_pointer] = arr[read_pointer]write_pointer += 1return write_pointer# 测试
arr = [1, 1, 2, 2, 3, 4, 4, 5]
length = remove_duplicates(arr)
print(arr[:length])  # 输出: [1, 2, 3, 4, 5]

总结

双指针算法通过巧妙地利用两个指针来遍历数据结构,能够在多种场景下提供高效的解决方案。以下是双指针算法的一些关键点:

  • 时间复杂度:通常可以将时间复杂度从 O(n^2) 降低到 O(n),显著提高效率。
  • 空间复杂度:大多数情况下,双指针算法的空间复杂度为 O(1),因为不需要额外的存储空间。
  • 灵活性:适用于多种数据结构和问题类型,包括数组、链表、字符串等。

希望这些详细的讲解和代码示例能帮助你更好地理解和应用双指针算法。如果你有任何进一步的问题或需要更多的示例,请随时告诉我。

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

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

相关文章

12 —— Webpack中向前端注入环境变量

需求&#xff1a;开发模式下打印语句生效&#xff0c;生产模式下打印语句失效 使用Webpack内置的DefinePlugin插件 const webpack require(webpack) module.exports { plugins: [ new webpack.DefinePlugin({ process.env.NODE_ENV:JSON.stringify(process.env.NODE_ENV) }…

【vba源码】导入excel批注信息

Hi&#xff0c;大家好呀&#xff01; 又到了一周一分享的时间&#xff0c;上周繁忙的我都没有给大家直播&#xff0c;视频也没更新&#xff0c;那这周大家放心&#xff0c;都会给大家更新&#xff0c;今天我们来讲点啥呢&#xff1f;每周找优质的内容给大家更新是我最最痛苦的…

Java设计模式 —— Java七大设计原则详解

文章目录 前言一、单一职责原则1、概述2、案例演示 二、接口隔离原则1、概述2、案例演示 三、依赖倒转原则1、概述2、案例演示 四、里氏替换原则1、概述2、案例演示 五、开闭原则1、概述2、案例演示 六、迪米特法则1、概述2、案例演示 七、合成/聚合复用原则1、概述2、组合3、聚…

服务器数据恢复—DS5300存储硬盘指示灯亮黄灯的数据恢复案例

服务器存储数据恢复环境&#xff1a; 某单位一台某品牌型号为DS5300的服务器存储&#xff0c;1个机头4个扩展柜&#xff0c;底层是2组分别由数十块硬盘组建的RAID5阵列。存储系统上层一共分了11个卷。 服务器存储故障&分析&#xff1a; 存储设备上一组raid5阵列上的2块磁盘…

Cloud Native 云原生后端的开发注意事项

在云原生后端开发里&#xff0c;数据管理和存储这块得好好弄。数据库选型得综合考虑&#xff0c;像关系型数据有复杂查询需求就选 MySQL、PostgreSQL&#xff0c;海量非结构化数据就可以考虑 MongoDB、Cassandra 这些。设计数据库得遵循规范化原则&#xff0c;像设计电商订单表…

Mac vscode 激活列编辑模式

列编辑模式在批量处理多行文本时&#xff0c;非常有效&#xff0c;但 vscode 默认情况下&#xff0c;又没有激活&#xff0c;因此记录一下启动方法&#xff1a; 激活列编辑模式 然后就可以使用 Alt&#xff08;Mac 上是 Option 或 Command 键&#xff09; 鼠标左键 滑动选择了…

c#使用高版本8.0步骤

一、找到项目所在怒路&#xff0c;记事本打开.proj文件。 二、记事本打开此文件&#xff0c;<PropertyGroup>后面加入如下语句&#xff1a; <LangVersion>8.0</LangVersion> 关闭并保存。 根据提示全部重新加载即可。

【蓝桥杯C/C++】深入解析I/O高效性能优化:std::ios::sync_with_stdio(false)

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: 蓝桥杯C/C 文章目录 &#x1f4af;前言&#x1f4af;C 语言与 C 语言的输入输出对比1.1 C 语言的输入输出1.2 C 语言的输入输出 &#x1f4af; std::ios::sync_with_stdio(false) 的作用与意义2.1 什么是 std::ios::sync_with_st…

浏览器的事件循环机制

一、请简述浏览器的事件循环机制&#xff08;Event Loop&#xff09;基本原理 浏览器的事件循环机制是用于协调处理 JavaScript 中的异步任务与同步任务执行顺序的一种机制&#xff0c;它确保了代码能够按照合理的顺序执行&#xff0c;避免阻塞页面渲染等情况。其基本原理如下…

GaussDB 华为高斯数据库

GaussDB 是华为推出的一款企业级分布式数据库&#xff0c;旨在为企业提供高效、可靠、安全的数据库服务。GaussDB 基于华为在数据库领域的多年积累&#xff0c;结合人工智能技术和分布式架构&#xff0c;支持多种场景的数据存储与管理需求&#xff0c;是云计算、大数据、人工智…

【Word】一键批量引用论文上标——将正文字体改为上标格式

【Word】一键批量引用论文上标——将正文字体改为上标格式 写在最前面Word一键批量引用论文上标技巧分享核心思路&#xff1a;Word 替换功能 通配符步骤详解1. 打开 Word 替换功能2. 输入通配符模式3. 设置替换格式为上标4. 批量替换 实际效果展示技巧扩展 &#x1f308;你好呀…

SAP 零售方案 CAR 系统的介绍与研究

前言 当今时代&#xff0c;零售业务是充满活力和活力的业务领域之一。每天&#xff0c;由于销售运营和客户行为&#xff0c;它都会生成大量数据。因此&#xff0c;公司迫切需要管理数据并从中检索见解。它将帮助公司朝着正确的方向发展他们的业务。 这就是为什么公司用来处理…

【深度学习之一】2024最新pytorch+cuda+cudnn下载安装搭建开发环境

兵马未动&#xff0c;粮草先行。作为深度学习的初学者&#xff0c;快速搭建一个属于自己的开发环境就是头等大事&#xff0c;可以让我们节省许多的时间。这一期我们主要讲一讲2024年最新pytorchcudacudnn下载安装搭建开发环境&#xff0c;以及安装过程中可能遇到的一些问题以及…

STM32-- 串口介绍

rs485、rs232、rs422 rs485使用&#xff1a; max3485&#xff1a;3.3v左右驱动 max485&#xff1a;5v左右驱动&#xff0c;不过有时候3.3v驱动也可以使用&#xff0c;具体有什么问题或者通过电路规避问题还没有了解过。 rs485和rs422有相同的地方&#xff0c;485满足422的规…

python oa服务器巡检报告脚本的重构和修改(适应数盾OTP)有空再去改

Two-Step Vertification required&#xff1a; Please enter the mobile app OTPverification code: 01.因为巡检的服务器要双因子认证登录&#xff0c;也就是登录堡垒机时还要输入验证码。这对我的巡检查服务器的工作带来了不便。它的机制是每一次登录&#xff0c;算一次会话…

AI安全:从现实关切到未来展望

近年来&#xff0c;人工智能技术飞速发展&#xff0c;从简单的图像识别到生成对话&#xff0c;从自动驾驶到医疗诊断&#xff0c;AI技术正深刻改变着我们的生活。然而&#xff0c;伴随着这些进步&#xff0c;AI的安全性和可控性问题也日益凸显。这不仅涉及技术层面的挑战&#…

c++ 笔记

基础知识 1. 指针、引用2. 数组3. 缺省参数4. 函数重载5. 内联函数6. 宏7. auto8. const9. 类和对象10. 类的6个默认成员函数11. 初始化列表12. this指针13. C/C的区别14. C 三大特性15. 结构体内存对齐规则16. explicit17. static18. 友元类、友元函数19. 内部类20. 内存管理&…

介绍一下strncmp(c基础)

strncmp是strcmp的进阶版 链接介绍一下strcmp(c基础)-CSDN博客 作用 比较两个字符串的前n位 格式 #include <string.h> strncmp (arr1,arr2,n); 工作原理&#xff1a;strcmp函数按照ACII&#xff08;字符编码顺序&#xff09;比较两个字符串。它从两个字符串的第一…

得物彩虹桥架构演进之路-负载均衡篇

文 / 新一 一、前言 一年一更的彩虹桥系列又来了&#xff0c;在前面两期我们分享了在稳定性和性能2个层面的一些演进&优化思路。近期我们针对彩虹桥 Proxy 负载均衡层面的架构做了一次升级&#xff0c;目前新架构已经部署完成&#xff0c;生产环境正在逐步升级中&#xf…

【ubuntu】数学人的环境搭建

Python 语言环境 python 的 pip 第三方库管理 sudo apt install python3-pippython 的 idle 界面 sudo apt install idle3R 语言环境 sudo apt install r-cran-zoo### RStudio 界面 ubuntu sudo snap install rstudio --classicJulia 语言环境 sudo snap install julia --…