双指针算法:快速解决问题的小技巧(Java代码实现)

embedded/2024/9/25 21:23:15/

“人的一生是短暂的,但如果卑鄙地过这短暂的一生,那就太长了。”

文章目录

  • 前言
    • 文章有误敬请斧正 不胜感恩!
    • 双指针
      • 简介
      • 对撞指针
      • 快慢指针
      • 例题
        • 聪明的小羊肖恩
        • 神奇的数组
        • 盛最多的水
  • 总结


前言

写在开始:
双指针算法是一种经典且高效的算法技巧,常用于数组、字符串等线性数据结构中的各种问题。它通过两个指针的协同移动,解决了传统暴力法需要 O(n²) 复杂度的问题,优化至 O(n)。双指针算法主要分为对撞指针和快慢指针两类,前者常用于解决有序数组和字符串的问题,后者更适合处理需要区间或步长变化的场景。掌握双指针技巧,不仅能提高解题效率,还能帮助我们更深入理解数据结构的特性与变化规律。

双指针算法其实就是通过两个“指针”来操作数据,虽然我们叫它指针,但实际上就是两个变量,
它们指的是数据中的不同位置。这个方法特别适合解决像数组、字符串这类线性结构的问题。
传统的暴力算法可能需要遍历很多次才能找到答案,而双指针通过巧妙的移动指针,
大大减少了重复操作,从而提高了效率。常见的双指针有两种,一种是从两边往中间走的对撞指针,
另一种是快慢指针,一个快一个慢,逐步缩小范围来解决问题。

在这里插入图片描述


文章有误敬请斧正 不胜感恩!

以下是本篇文章正文内容,


双指针

简介

双指针算法是一种常用的算法技巧,它通常用于在数组或字符串中进行快速查找、匹配、排序或移动操作

双指针并非真的用指针实现,一般用两个变量来表示下标 (在后面都用指针来表示)

双指针算法使用两个指针在数据结构上进行迭代,并根据问题的要求移动这些指针

双指针往往也和单调性、排序联系在一起,在数组的区间问题上,暴力法的时间复杂度往往是O(n^2)的,但双指针利用“单调性”可以优化到O(n).

常见的双指针模型有:

  1. 对撞指针
  2. 快慢指针

对撞指针

指的是两个指针 left、right (简写为l,r) 分别指l向序列第一个元素和最后一个元素

然后l指针不断递增,r不断递减,直到两个指针的值相撞或错开 (即 l >= r),或者满足其他要求的特殊条件为止。

对撞指针一般用来解决有序数组或者字符串问题 (常见于区间问题)

查找有序数组中满足某些约束条件的一组元素问题: 比如二分查找、数字之和等问题字符串反转问题:反转字符串、回文数等问题.

  1. 使用两个指针 left,right。let 指向序列第一个元素,即: left = l,right 指向序列最后一个元素,即: right = n。
  2. 在循环体中将左右指针相向移动,当满足一定条件时,将左指针右移,let ++。当满足另外定条件时,将右指针左移,right –
  3. 直到两指针相撞(即 left == right),或者满足其他要求的特殊条件时,跳出循环体

img

快慢指针

快慢指针一般比对撞指针更难想,也更难写

指的是两个指针从同一侧开始遍历序列,且移动的步长一个快一个慢

移动快的指针被称为快指针,移动慢的指针被称为慢指针

为了方便理解,我们成快指针为r,慢指针为1,这样慢指针和快指针构成区间[l,r]

两个指针以不同速度、不同策略移动,直到快指针移动到数组尾端,或者两指针相交,或者满足其他特殊条件时为止

  1. 使用两个指针1、r1一般指向序列第一个元素,即: 1= 1,r一般指向序列第零个元素,即:r = 0。即初始时区间[l, r]= [1,]表示为空区间
  2. 在循环体中将左右指针向右移动。当满足一定条件时,将慢指针右移,即1++。当满足另外一定条件时 (也可能不需要满足条件) ,将快指针右移,即r++,保持[l,r]为合法区间
  3. 到指针移动到数组尾端 (即l== n且r== n),或者两指针相交,或者满足其他特殊条件时跳出循环体

img

例题

聪明的小羊肖恩
java">import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();int left = scan.nextInt();int right = scan.nextInt();int[] arr = new int[n];for(int i=0;i<n;i++){arr[i] = scan.nextInt();}Arrays.sort(arr);System.out.println(calc(arr,right)-calc(arr,left-1));scan.close();}static long calc(int[] arr,int t){long ans = 0;int l = 0 , r = arr.length - 1;while(l < r){while(l<r && arr[r] + arr[l] > t){r--;}ans += r - l;l++;}return ans;}
}
神奇的数组
java">import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();int[] arr = new int[n];for(int i=0;i<n;i++){arr[i] = scan.nextInt();}int l=0,r=0,rs=0;long ans = 0;while(l<n){while(r<n && ((rs^arr[r]) == (rs + arr[r]))){rs ^= arr[r];r++;}ans += r - l;rs ^= arr[l];l++;}System.out.println(ans);scan.close();}
}
盛最多的水

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

java">class Solution {public int maxArea(int[] height) {int i = 0, j = height.length - 1, res = 0;![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/056355574f954b2794e5e37b99b20360.jpeg#pic_center)res = height[i] < height[j] ?Math.max(res, (j - i) * height[i++]):Math.max(res, (j - i) * height[j--]);}return res;}
}

总结

双指针算法的核心在于两个指针的相互配合,通过灵活调整指针的移动策略,能够有效地解决很多复杂度较高的问题。无论是对撞指针,还是快慢指针,都是在特定场景下优化问题求解的一种利器。在面对算法问题时,我们要善于通过分析数据的单调性、区间的划分来运用双指针算法,从而提升代码的效率和简洁性。


在这里插入图片描述


http://www.ppmy.cn/embedded/113626.html

相关文章

保护您的隐私:隐藏 IP 地址的重要性

在当今的数字时代&#xff0c;我们的在线隐私和安全变得比以往任何时候都更加重要。浏览互联网时保护自己的一种方法是隐藏您的 IP 地址。 但是为什么要隐藏您的 IP 地址以及如何有效地做到这一点&#xff1f; 隐藏您的 IP 地址有助于保护您的在线匿名性。您的 IP 地址就像您的…

需要申请 TAC

需要申请 TAC&#xff1f; https://www.gsma.com/solutions-and-impact/industry-services/device-services/tac-allocation?langzh-hans 3GPP 要求所有可以连接到移动无线网络的设备类型都能通过 Type Allocation Code (TAC) 来识别&#xff0c;包括 IoT 设备、支付终端和联…

集群聊天服务器项目【C++】项目介绍和环境搭建

前言&#xff1a;学习一个基于C集群聊天服务器的项目&#xff0c;记录学习的内容和学习的过程。 1.项目介绍 在 Linux 环境下基于 muduo 开发的集群聊天服务器。实现新用户注册、用户登录、添加好友、添加群组、好友通信、群组聊天、保持离线消息等功能。 2.技术栈 Json序列…

Java-获取对象字段名并遍历处理

在Java中,可以通过反射(Reflection)来获取对象的所有字段名。以下是一个详细的示例,展示 了如何使用反射获取对象的所有字段名,并对其进行遍历处理。 package com.nanjing.gulimall.zhouyimo;/*** @author zhou* @version 1.0* @date 2024/9/18 10:11 下午*/ public cla…

linux-Linux 内核与模块管理-内核模块管理

Linux 内核与模块管理&#xff1a;内核模块管理概述 Linux 内核是操作系统的核心部分&#xff0c;负责管理系统资源并为应用程序提供基础服务。为了提升系统的可扩展性和灵活性&#xff0c;Linux 支持一种称为“内核模块”的机制。内核模块是一段独立的代码&#xff0c;它可以…

Harmony Next 文件命令操作(发送、读取、媒体文件查询)

查询文件位置 hdc shell mediatool query IMG_20240902_204224.jpg 输出示例 拉取文件 hdc file recv /storage/cloud/100/files/Photo/4/IMG_1725281044_036.jpg aa.jpg 发送文件 hdc file send aa.jpg /storage/media/100/local/files/Docs/Download/ab.jpg 下载目录位置…

SEAFARING靶场漏洞攻略

寻找漏洞 一&#xff0c;我们打开页面 第一个漏洞 xss漏洞 1.在登录页面显示有弹窗 第二个漏洞 sql注入漏洞 1.在输入框的地方输入-1 union select 1,2,3#我们来查看他的回显点 2.查看数据库表名 -1 union select 1,database(),3# 3.查看表名 -1 union select 1,2,group…

SQL使用IN进行分组统计时如何将不存在的字段显示为0

这两天被扔过来一个脏活儿&#xff1a;做一个试点运行系统的运营指标统计。 活儿之所以称为“脏”&#xff0c;是因为要统计8家单位共12个项目的指标。而每个项目有3个用户类指标&#xff0c;以及分17个功能模块&#xff0c;每个功能模块又分5个维度的指标。也就是单个项目是1…