Leetcode | 对撞指针算法笔记

这篇具有很好参考价值的文章主要介绍了Leetcode | 对撞指针算法笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

对撞指针基本思想

对撞指针的基本思想是在数组或链表等数据结构中使用两个指针(leftrightstartend等表示),分别从不同的方向(通常是数组的两端)移动,以便有效地进行搜索、遍历或判断

对撞指针常见的运用场景包括:

  1. 排序数组的查找:对撞指针可以用于在已排序的数组中搜索目标元素。通过将一个指针指向数组的起始位置,另一个指针指向数组的末尾位置,根据指针所指元素与目标元素的大小关系,逐步向中间移动指针,以达到快速搜索目标元素的目的。

  2. 有序数组的两数之和:给定一个有序数组和一个目标数,可以使用对撞指针的方法在数组中找到两个数,使它们的和等于目标数。通过将一个指针指向数组的起始位置,另一个指针指向数组的末尾位置,根据指针所指元素的和与目标数的大小关系,逐步移动指针,以找到满足条件的两个数。

  3. 回文字符串判断:对撞指针可以用于判断一个字符串是否是回文字符串。通过将一个指针指向字符串的起始位置,另一个指针指向字符串的末尾位置,逐步向中间移动指针,并比较两个指针所指的字符是否相等,以判断字符串是否回文。

  4. 链表操作:使用对撞指针找到链表的中间节点、判断链表是否有环等。

  5. ……

对撞指针的优势在于它能够在单次遍历中完成任务,时间复杂度通常较低,且不需要额外的空间

但是,使用对撞指针的前提是目标数据结构需要满足一定的条件,比如有序或有特定的结构性质。

对撞指针相关习题

两数之和 II - 输入有序数组

题目描述

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1]numbers[index2] ,则 1 <= index1 < index2 <= numbers.length

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标index1 index2

  • 你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

  • 你所设计的解决方案必须只使用常量级的额外空间。

题目分析与实现

数据结构:数组

基本实现方法:

  • 对撞指针
实现一:对撞指针
# Use Python to solve
def two_sum(numbers, target):
    '''
    查找满足两数之和的位置
    
    参数:
    	numbers(list[int]): 非递减顺序排列的整数数组
    	target(int): 目标数
    返回值:
    	两个整数的下标    	
    '''
    
    # left指针从左往右运动
    # right指针从右往左运动
    left = 0
    right = len(numbers) - 1
    
    while left < right:
        current_sum = numbers[left] + numbers[right]
        # 如果左右指针之和大于目标数,说明right指针需要往左移动一位
        # 反之,left指针需要往右移动一位,通过这样的方式可以有效地缩小搜索空间
        if current_sum > target:
            right -= 1
        elif current_sum < target:
            left += 1
        else:            
   			 return left + 1, right + 1

时间复杂度分析:

  • 平均时间复杂度: O ( n ) O(n) O(n),其中 n 是数组的长度。在最坏的情况下,左指针和右指针分别从数组的两端向中间移动,直到找到满足条件的两个数或者左指针和右指针相遇。平均情况下,可以近似认为左右指针在数组的中间位置相遇,因此需要遍历整个数组一次。
  • 最好时间复杂度: O ( 1 ) O(1) O(1),当数组中不存在目标值时,只需遍历一次数组,即左右指针分别指向数组的首尾元素,然后直接返回结果。
  • 最坏时间复杂度: O ( n ) O(n) O(n),当数组中的所有元素都等于目标值时,需要遍历整个数组,即左右指针从两端向中间移动直到相遇。

空间复杂度分析:文章来源地址https://www.toymoban.com/news/detail-526069.html

  • O ( 1 ) O(1) O(1),使用了常数个额外空间。

验证回文串

题目描述

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

  • 字母和数字都属于字母数字字符。
  • 给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
题目分析与实现

数据结构:数组

基本实现方法:

  • 对撞指针
实现一:对撞指针
  1. 首先使用Python中的字符串API:isalnum(),用于检查字符串中的所有字符是否都是字母和数字字符(即字母或数字),返回值为布尔值。
  2. 然后,通过两个指针:leftrightleft < right)从两边向中间移动逐一判断leftright是否相等
  3. 若双方的值不相等,说明不是回文串,直接返回False
  4. 若相等,left前进一步,right后退一步继续进行判断,直到双方达到字符串中间部分。
# Use Python to solve
def is_palindrome(string):
    '''
    检验给定字符串中是否是回文
    参数:
        string (str): 给定字符串
    
    返回值:
        bool
    '''
    
    cleaned_string = "".join(ch.lower() for ch in string if ch.isalnum())
    
    left = 0
    right = len(cleaned_string) - 1
    # 左右指针向字符串中间进发
    while left < right:
        # 如果发现不等,直接返回False
        if cleaned_string[left] != cleaned_string[right]:
            return False
        # 若left和right的值相等,双方继续向中间进发
        left, right = left + 1, right - 1
    # 若遍历完成,说明该字符串是一个回文串
    return True

时间复杂度分析:

  • 平均时间复杂度: O ( n ) O(n) O(n),其中 n 是字符串的长度。在平均情况下,需要遍历字符串一次来构建新的字符串 cleaned_string,其中只包含字母和数字,并且转换为小写字母。然后,需要再次遍历 cleaned_string 的一半来检查是否满足回文的条件。因此,时间复杂度是线性的,即 O ( n ) O(n) O(n)
  • 最好时间复杂度: O ( 1 ) O(1) O(1),当字符串为空字符串时,直接返回结果 True,无需进行任何操作。
  • 最坏时间复杂度: O ( n ) O(n) O(n),当字符串是一个回文字符串时,需要遍历整个字符串的一半,即左右指针从两端向中间移动。

空间复杂度分析:

  • O ( n ) O(n) O(n),创建了一个新的字符串 cleaned_string ,其中存储了输入字符串中的字母和数字,并转换为小写字母。

反转字符串中的元音字母

题目描述

给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。元音字母包括 'a''e''i''o''u',且可能以大小写两种形式出现不止一次。

题目分析与实现

数据结构:数组

基本实现方法:

  • 对撞指针
实现一:对撞指针

我们可以使用两个指针 i i i j j j 对字符串相向地进行遍历。

  1. 首先指针 i i i 初始时指向字符串 s s s 的首位,指针 j j j 初始时指向字符串 s s s 的末位。
  2. 在遍历的过程中,我们不停地将 i i i 向右移动,直到 i i i 指向一个元音字母
  3. 同时,我们不停地将 j j j 向左移动,直到 j j j 指向一个元音字母。
  4. 此时,如果 i < j i<j i<j,那么我们交换 i i i j j j 指向的元音字母,否则说明所有的元音字母均已遍历过,就可以退出遍历的过程。
# Use Python to solve
def reverse_vowels(s):
    '''
    反转给定字符串中的元音字母
    
    参数:
        s (str): 一个给定字符串
    
    返回值:
        str: 完成反转后的字符串    
    '''
    char_list = list(s)
    length = len(s)
    left = 0
    right = length - 1
    vowel_list = ['a', 'e', 'i', 'o', 'u',
                  'A', 'E', 'I', 'O', 'U']
    while left < right:
        # 在每次循环迭代中,判断 char_list[left](或char_list[right) 是否为元音字母且 left 小于 right,
        # 如果不是,则将 left (或right)指针向右(或左)移动,直到找到一个元音字母。
        while char_list[left] not in vowel_list and left < right:
            left += 1
        while char_list[right] not in vowel_list and left < right:
            right -= 1
        # 找到两个元音字母后,将它们进行反转
        # 然后,将 left 指针向右移动一位,将 right 指针向左移动一位,以继续下一轮迭代。
        char_list[left], char_list[right] = char_list[right], char_list[left]
        left += 1
        right -= 1
    # 最后,使用将字符列表转换为字符串,并将其作为函数的返回值
    return "".join(char_list)

时间复杂度分析:

  • 平均时间复杂度: O ( n ) O(n) O(n),其中 n 是字符串的长度。在最坏的情况下,左指针 left 和右指针 right 分别从字符串的两端向中间移动,直到找到满足条件的两个元音字母或者 leftright 相遇。平均情况下,可以近似认为左右指针在字符串的中间位置相遇,因此需要遍历整个字符串一次。
  • 最好时间复杂度: O ( 1 ) O(1) O(1),当字符串中没有元音字母时,只需遍历一次字符串,即左右指针初始时在同一位置,然后直接返回结果。
  • 最坏时间复杂度: O ( n ) O(n) O(n),当字符串中的所有字符都是元音字母时,需要遍历整个字符串,即左右指针从两端向中间移动直到相遇。

空间复杂度分析:

  • O ( n ) O(n) O(n),其中 n 是字符串的长度。

盛最多水的容器

题目描述

给定一个长度为 n n n 的整数数组 h e i g h t height height 。有 n n n 条垂线,第 i i i 条线的两个端点是 ( i , 0 ) (i, 0) (i,0)
( i , h e i g h t [ i ] ) ( i, height[i]) (i,height[i])

找出其中的两条线,使得它们与 x x x 轴共同构成的容器可以容纳最多的水。

  • 返回容器可以储存的最大水量。
题目分析与描述

数据结构:数组

基本实现方法:

  • 对撞指针
实现一:对撞指针
# Use Python to solve
def max_area(height):
    '''
    解决最大容器问题
    
    参数:
    	height(int): 给定整数数组,表示容器的高度
    	
    返回值:
    	int:最大可容纳水量    
    '''
    # 初始化双指针和最大面积
    left = 0
    right = len(height) - 1
    max_area = 0
	
    # 两个指针向中间移动
    while left < right:
        # 比较两个指针,找到最小的那个
        # 谁小,谁移动
        if height[left] < height[right]:
           max_area = max(max_area, (right - left) * height[left])
           left += 1                
        else:
           max_area = max(max_area, (right - left) * height[right])
           right -= 1
            
    return max_area

时间复杂度分析:

  • 平均时间复杂度: O ( n ) O(n) O(n),其中 n 是容器高度数组的长度。在平均情况下,使用双指针的方法遍历数组一次,通过比较左右指针所指的高度来确定木桶的最小高度,然后计算并更新当前的最大面积。因此,时间复杂度是线性的,即 O ( n ) O(n) O(n)
  • 最好时间复杂度: O ( 1 ) O(1) O(1),当容器高度数组为空或只包含一个元素时,直接返回结果 0,无需进行任何操作。
  • 最坏时间复杂度: O ( n ) O(n) O(n),当容器高度数组形成一个大的斜坡(高度递增或递减)时,需要遍历整个数组一次。

空间复杂度分析:

  • O ( 1 ) O(1) O(1),使用了常数个额外空间。

到了这里,关于Leetcode | 对撞指针算法笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【算法】排序+双指针——leetcode三数之和、四数之和

    【算法】排序+双指针——leetcode三数之和、四数之和

    三数之和 (1)排序+双指针   算法思路: 和之前的两数之和类似,我们对暴力枚举进行了一些优化,利用了 排序+双指针 的思路:   我们先排序,然后固定⼀个数 a ,接着我们就可以在这个数后面的区间内,使用之前两数之和使用的算法,快速找到两个数之和和固定的

    2024年02月13日
    浏览(16)
  • 【算法|双指针系列No.2】leetcode1089. 复写零

    【算法|双指针系列No.2】leetcode1089. 复写零

    个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月13日
    浏览(9)
  • leetcode做题笔记138. 复制带随机指针的链表

    给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 

    2024年02月07日
    浏览(15)
  • 算法修炼之路之双指针含多道leetcode 经典题目

    算法修炼之路之双指针含多道leetcode 经典题目

    目录 前言  一:普通双指针 1.经典题目一  283移动0问题 分析 代码实现 2.经典题目二 1089复写0  分析 代码实现 二:解决成环类问题-快慢指针  经典例题一 202快乐数 分析  代码实现   三:左右相遇指针 经典例题一 11 盛最多水的容器 分析  代码实现    接下来的日子会顺

    2024年04月13日
    浏览(10)
  • 【算法|双指针系列No.4】leetcode11. 盛最多水的容器

    【算法|双指针系列No.4】leetcode11. 盛最多水的容器

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(10)
  • leetcode做题笔记116. 填充每个节点的下一个右侧节点指针

    给定一个  完美二叉树  ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为  NULL 。 初始状态下,所有 next 指针都被设置为  NULL 。

    2024年02月10日
    浏览(10)
  • 【算法】双指针——leetcode盛最多水的容器、剑指Offer57和为s的两个数字

    【算法】双指针——leetcode盛最多水的容器、剑指Offer57和为s的两个数字

    盛水最多的容器 (1)暴力解法   算法思路:我们枚举出所有的容器大小,取最大值即可。   容器容积的计算方式:   设两指针 i , j ,分别指向水槽板的最左端以及最右端,此时容器的宽度为 j - i 。由于容器的高度由两板中的较短的板决定,因此可得容积公式 :

    2024年02月13日
    浏览(12)
  • LeetCode | 一探环形链表的奥秘【快慢双指针妙解BAT等大厂经典算法题】

    LeetCode | 一探环形链表的奥秘【快慢双指针妙解BAT等大厂经典算法题】

    前言 本文总结了力扣141.环形链表|以及142.环形链表||这两道有关环形链表的求解方案,去求证链表是否带环已经如何找出入环口的结点。 有关环形链表,在BAT等大厂面试中均有出现,一般是属于 中等难度 的题,需掌握 原题传送门 给你一个链表的头节点 head ,判断链表中是

    2024年02月01日
    浏览(10)
  • leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

    leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

    我的往期文章: leetCode 647.回文子串 动态规划 + 优化空间 / 中心扩展法 + 双指针-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/133883091?spm=1001.2014.3001.5501 leetCode 131.分割回文串 + 回溯算法 + 图解 + 笔记-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/134700907?spm=1001.2014.3001

    2024年02月05日
    浏览(29)
  • 【LeetCode】 双指针,快慢指针解题

    【LeetCode】 双指针,快慢指针解题

    1.删除有序数组中的重复项 2.移除元素

    2024年02月11日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包