LeetCode - 双指针(Two Pointers) 算法集合 [对撞指针、快慢指针、滑动窗口、双链遍历]

本文主要是介绍LeetCode - 双指针(Two Pointers) 算法集合 [对撞指针、快慢指针、滑动窗口、双链遍历],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎关注我的CSDN:https://spike.blog.csdn.net/
本文地址:https://spike.blog.csdn.net/article/details/139270999

Two Sum

双指针算法是一种常见且灵活的技巧,通过使用两个指针协同完成任务。这些指针可以指向不同的元素,具体应用取决于问题的性质。双指针算法的常见用法:

  1. 对撞指针:一左一右向中间逼近。例如,反转字符串中的元音字母问题,可以使用对撞指针。
  2. 快慢指针:一快一慢,步长不同。例如,判断链表中是否有环问题,可以使用快慢指针,看慢指针是否能追上快指针。单链表找中间节点问题也可以用快慢指针,快指针到链表结尾,慢指针到一半。
  3. 滑动窗口:类似计算机网络中的滑动窗口。一般是右端向右扩充,达到停止条件后右端不动,左端向右端逼近,逼近达到停止条件后,左端不动,右端继续扩充。

双指针算法包括:对撞指针快慢指针滑动窗口双链遍历

  1. 167. 两数之和 II - 输入有序数组 - 对撞指针
  2. 633. 平方数之和 - 对撞指针,题目167变种
  3. 680. 验证回文串 II - 对撞指针,需要判断去除1个字符 l+1 或 r-1
  4. 15. 三数之和 - 两数之和的进阶版,先排序,逐步修改序列
  5. 142. 环形链表 II - 快慢指针
  6. 76. 最小覆盖子串 - 滑动窗口,Counter类的使用
  7. 88. 合并两个有序数组 - 双链遍历
  8. 524. 通过删除字母匹配到字典里最长单词 - 双链遍历,优先排序,再依次比较。

1. 对撞指针

167. 两数之和 II - 输入有序数组 - 对撞指针

class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:"""时间复杂度O(n),空间复杂度O(1)"""# 输入的已经排序n=len(numbers)  # 数量l,r=0,n-1  # 左右指针while l<r:v=numbers[l]+numbers[r]  # 两数之和if v>target: # 移动指针r-=1elif v<target:l+=1else:return [l+1,r+1]

633. 平方数之和 - 对撞指针,167变种

class Solution:def judgeSquareSum(self, c: int) -> bool:"""时间复杂度 O(n),空间复杂度 O(1)"""# 左右指针l, r = 0, int(sqrt(c))while l <= r:  # 遍历条件需要相等# 计算值v = pow(l, 2) + pow(r, 2)if v > c:  # 移动右指针r -= 1elif v < c:  # 移动左指针l += 1else:return Truereturn False

680. 验证回文串 II - 对撞指针,需要判断去除1个字符 l+1 或 r-1

class Solution:def validPalindrome(self, s: str) -> bool:"""时间复杂度 O(n), 空间复杂度 O(1)"""def check(l, r):"""检查s是否是回文"""while l < r:if s[l] == s[r]:l += 1r -= 1else:return Falsereturn Truen = len(s)l, r = 0, n-1  # 左右指针while l < r:if s[l] == s[r]:  # 回文l += 1r -= 1else:# 越过1个值,最多可以从中删除一个字符return check(l+1, r) or check(l, r-1)return True

15. 三数之和 - 两数之和的进阶版,先排序,逐步修改序列

class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:"""时间O(N^2),空间O(logN) -> 排序"""def two_sum(nums, t):"""经典的两数之和,同时,避免重复添加"""n = len(nums)l, r = 0, n-1res = []while l < r:x = nums[l] + nums[r]if x > t:r -= 1elif x < t:l += 1else:sr = [nums[l], nums[r], -t]if sr not in res:  # 避免重复添加res.append(sr)l += 1return resnums.sort()  # 排序n = len(nums)  # 序列长度res = []  # 输出结果for i in range(n):# 避免重复数字if i > 0 and nums[i-1] == nums[i]:continuet = nums[i]  # 依次遍历res += two_sum(nums[i+1:], -t)return res

2. 快慢指针

142. 环形链表 II - 快慢指针

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:"""时间复杂度O(n),空间复杂度O(1)"""if not head:return None# 快慢指针先指向headslow=fast=head# 判断是否运行到结尾while fast.next and fast.next.next:slow=slow.next  # 移动1步fast=fast.next.next  # 移动2步if slow==fast:fast=head # fast从head开始重新计数while slow!=fast:  # 移动到位置slow=slow.nextfast=fast.nextreturn fast # 相等即返回return None

3. 滑动窗口

76. 最小覆盖子串 - 滑动窗口

class Solution:def minWindow(self, s: str, t: str) -> str:"""时间复杂度 O(m+n),空间复杂度 O(1)"""rl,rr=-1,len(s) # 目标的最大窗口l=0  # 左指针cnt_s=Counter()  # 计数器字典cnt_t=Counter(t) # 目标计数器字典less=len(cnt_t)  # 不重复的t字母数量for r,c in enumerate(s):cnt_s[c]+=1  # s计数器if cnt_s[c]==cnt_t[c]:  # 数量相等less-=1  # 数量减一while less==0:  # 满足条件if r-l < rr-rl:  # 区间更小rl,rr=l,r  # 更新左右指针# -----# 如果数量相等,之后数量需要减一,所以less需要提前+1x=s[l]  # 左指针当前字母if cnt_s[x]==cnt_t[x]:  less+=1  # 不重复+1cnt_s[x]-=1  # 指针减1l+=1  # 已经更新,所以需要移动左指针# -----return "" if rl<0 else s[rl:rr+1]

4. 双链遍历

88. 合并两个有序数组 - 双链指针

class Solution:def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:"""Do not return anything, modify nums1 in-place instead.时间复杂度 O(n),空间复杂度 O(1)"""pos=(m-1)+(n-1)+1  # 最远位置m-=1  # 最后位置n-=1  # 最后位置while m>=0 and n>=0:  # 遍历两个数组# 注意: 大于等于确保,优先移动mif nums1[m]>=nums2[n]:nums1[pos]=nums1[m]  # 赋值大值m-=1else:nums1[pos]=nums2[n]n-=1pos-=1  # 移动指针while n>=0: # 优先移动m,所以剩下的就是nnums1[pos]=nums2[n]pos-=1n-=1

524. 通过删除字母匹配到字典里最长单词 - 双链指针,优先排序,再依次比较。

class Solution:def findLongestWord(self, s: str, dictionary: List[str]) -> str:"""d 是字典长度,m 是s长度时间复杂度 O(d x (m+n)),空间复杂度 O(d x m)"""# 按目标结果排序,优先做前面的words = sorted(dictionary, key=lambda x: (-len(x), x))for t in words:i = j = 0  # 双指针while i < len(t) and j < len(s): # 双指针遍历if t[i] == s[j]:  # 相同i += 1  # t指针+1,满足条件j+=1  # s指针默认都+1if i == len(t):  # 长度满足return t  # 直接返回return ""

这篇关于LeetCode - 双指针(Two Pointers) 算法集合 [对撞指针、快慢指针、滑动窗口、双链遍历]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012576

相关文章

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python容器类型之列表/字典/元组/集合方式

《Python容器类型之列表/字典/元组/集合方式》:本文主要介绍Python容器类型之列表/字典/元组/集合方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 列表(List) - 有序可变序列1.1 基本特性1.2 核心操作1.3 应用场景2. 字典(D

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

Java集合中的List超详细讲解

《Java集合中的List超详细讲解》本文详细介绍了Java集合框架中的List接口,包括其在集合中的位置、继承体系、常用操作和代码示例,以及不同实现类(如ArrayList、LinkedList和V... 目录一,List的继承体系二,List的常用操作及代码示例1,创建List实例2,增加元素3,访问元

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(