leetcode刷题——双指针


双指针法分为滑动窗口、左右指针、快慢指针、首尾指针三种。

滑动窗口左右指针快慢指针首尾指针
left和right的初始化和更新left用数字初始和更新,right用循环初始和更新left用数字初始和更新,right用循环初始和更新slow、fast从起点出发,但速度一慢一快,如果有循环结构,则快指针一定会追上慢指针left和right分别从首、尾向中间移动
left和right的作用left和right用于记录窗口的左右边缘left用于更新记录,right用于遍历两者相交表示有循环结构left和right用于更新左右两端的数字
解决问题子串、子数组问题遍历中的更新记录问题判断是否存在循环结构有序数组中的查找两个数,时间复杂度O(n)优于二分查找O(nlogn);无序数组找最佳边界

左右指针

  • 适用问题:列表、字符串原地按要求删除、移动、更新元素
  • 一个指针指向要替换的位置,一个指针遍历

27. 移除元素

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        # i指向要替换的位置(下一个应该被填充的位置),j用于遍历
        # j没有遇到val就写到i的位置,遇到就i不动j向前
        slow,fast=0,0  
        while fast<=len(nums)-1:  
            if nums[fast]!=val:
                nums[slow]=nums[fast]
                slow+=1
            fast+=1
        return slow

26.删除排序数组中的重复项

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # left负责记录结果,right负责遍历
        # 保留不重复的结果
        left=1
        for right in range(1,len(nums)):
            if nums[right]!=nums[right-1]:
                nums[left]=nums[right]
                left+=1
        return left

283. 移动零

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        j=0
        for i in range(len(nums)):
            if nums[i]!=0:
                nums[j],nums[i]=nums[i],nums[j]
                j+=1
        return nums
class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        def tran_word(s):
            s=list(s)
            left,right=0,0
            for right in range(len(s)):
                if s[right]!='#':
                    s[left]=s[right]
                    left+=1
                elif s[right]=='#' and left>0:
                    left-=1
                # 如果遇到#且left已经到达最左端,就继续遍历
            return ''.join(s[:left])
        return tran_word(s)==tran_word(t)

844. 比较含退格的字符串

class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        def tran_word(s):
            s=list(s)
            left,right=0,0
            for right in range(len(s)):
                if s[right]!='#':
                    s[left]=s[right]
                    left+=1
                elif s[right]=='#' and left>0:
                    left-=1
                # 如果遇到#且left已经到达最左端,就继续遍历
            return ''.join(s[:left])
        return tran_word(s)==tran_word(t)

344.反转字符串
剑指Offer 05.替换空格
151.翻转字符串里的单词(综合题)
206.反转链表
19.删除链表的倒数第N个节点

快慢指针

面试题 02.07. 链表相交
142.环形链表II

首尾指针

  • 两个指针从首尾开始遍历

344.反转字符串
第15题. 三数之和
第18题. 四数之和

一、适用问题

连续子串、连续子数组

二、类型

  1. 固定长度的窗口,用if
  2. 可变长度的窗口,用while

三、思路

01- 初始化维护变量、非维护变量、左右窗口
02-移动right,更新维护变量
03- right不动,更新left,更新维护变量
04-输出结果

三、常见问题

a. 输出结果的位置
b. 两端最大<>中间连续最小【Day1]
c. 窗口起标记作用,输出结果用到了这个标记【Day6】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值