双指针法

双指针法

双指针法三类

  • 左右双指针算法
  • 快慢双指针算法
  • 后序双指针算法

左右双指针算法

左右双指针算法基本思想

左右双指针算法在解决问题的过程中会生成两个指针,一个指向头部,一个指向尾部,从两端向中间逼近,直到满足条件或者两个指针相遇为止. 二分查找就是一种左右双指针算法的应用场景,其他使用情况基本上可以总结为数组中元素组合问题。

经典例题:三数之和

在这里插入图片描述

  • 该问题是采用左右双指针算法解决的经典问题之一,以三数之和为限制条件,适当调整左右指针。
def threeSum(array):
    """左右双指针"""
    array.sort()
    res=[]

    for k in range(len(array)-2):
        if array[k] >0:break
        #先固定一个数,若这个数与上个数重复,则去重
        if k>0 and array[k] == array[k-1]:continue

        """l指向前节点、r指向尾节点"""
        l,r=k+1,len(array)-1
        while l<r:
            s=array[k]+array[l]+array[r]
            if s<0:
                #指向前节点的指针向右移
                l+=1
                #对重复的元素去重,并且向右移
                while l<r and array[l]==array[l-1]:l+=1

            elif s>0:
                #指向尾节点的指针向左移
                r-=1
                while l<r and array[r]==array[r+1]:r-=1

            else:
                #若s=0,则构造可行解
                res.append([array[k],array[l],array[r]])
                l+=1
                r-=1
                #元素去重
                while l<r and array[l]==array[l-1]:l+=1
                while l<r and array[r]==array[r+1]:r-=1

    return res

快慢双指针法

快慢双指针思想

快慢双指针在解决问题的过程中会使用两个指针,两个指针的起始位置相同,但是在遍历过程中前景速度不同,如慢指针一次前进一步,块指针一次前进两步,通过这样的方式达到目的。快慢双指针算法一般的适用情况有:链表求环、链表求中点、数组中元素替换与查找等问题

经典例题:链表求环

在这里插入图片描述

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        #考虑特殊情况
        if head is None:
            return 

        #快慢双指针初始化
        fast=head
        slow=head

        while(fast):
            #如果fast指针指向None,说明无环
            if fast.next== None:
                return False

            #fast每次移动两步、slow每次移动一步
            fast=fast.next.next
            slow=slow.next
            #如果fast==slow,说明快指针追上了慢指针,说明有环
            if fast == slow:
                return True
经典例题二:回文链表

在这里插入图片描述

解题思路

解决这个问题,我们需要考虑两点:

  • 寻找原始链表的中间节点
  • 对后半部分链表做反转
    最终如果后半部分反转的链表与前半部分链表完全一致,说明该链表是回文链表!
class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        #考虑特殊情况
        if head == None or head.next == None:
            return True

        #指针初始化
        fast=head
        slow=head

        #寻找中间节点
        while (fast.next!=None) and (fast.next.next!=None):
            fast=fast.next.next
            slow=slow.next

        #不论head链表是偶数还是奇数  slow都是中间节点,因此反转后半部分节点传递slow.next
        def reverselink(head):
            #head表示当前节点、current表示当前节点的下一个节点、pre表示当前节点的上一个节点
            #该函数返回反转链表的头指针
            current=None
            pre=None

            while(head!=None):
                #链表反转四步骤
                current=head.next
                head.next=pre
                pre=head
                head=current

            return pre

        start=reverselink(slow.next)
        #对比反转链表与前半部分链表的个节点是否相同
        while(start):
            if(start.val != head.val ):
                return False
            start=start.next
            head=head.next

        return True
两个数组的交集

在这里插入图片描述

解题思路
  • 先对两数组进行排序,创建两个指针,起始为零。遍历两数组,当一个数组值小于另外一个数组时,让该数组的指针右移;当一个数组值等于另外一个数组值时,让两个数组的指针右移;直到有一个指针超出了数组长度,跳出循环。
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()

        #初始化参数
        n1,n2=len(nums1),len(nums2)
        res=[]
        index1=index2=0

        while index1<n1 and index2<n2:
            if nums1[index1]<nums2[index2]:
                index1+=1
            elif nums1[index1]>nums2[index2]:
                index2+=1
            else:
                res.append(nums1[index1])
                index1+=1
                index2+=1

        return res
奇偶排序

在这里插入图片描述

解题思路:
  • 开辟一个新的空间,将偶数部分存储到A[0]、A[2]、A[4]……将奇数部分存储到A[1]、A[3]、A[5]……
class Solution:
    def sortArrayByParityII(self, A: List[int]) -> List[int]:
        #两次遍历  将奇数存到  a[1]、a[3]……
        n=len(A)
        alist=[None]*n

        t=0
        for i in A:
            if i%2==0:
                alist[t]=i
                t+=2
        
        t=1
        for i in A:
            if i%2==1:
                alist[t]=i
                t+=2
        
        return alist
删除链表的倒数第几个元素

在这里插入图片描述

	class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
    	# 创建一个哑节点,这样一来就无需对头节点进行判断
        dummy = ListNode(0)
        dummy.next = head 
        
        # 1. 快指针先走
        fast = slow = dummy
        for i in range(n):
            fast = fast.next

        # 2. 快慢指针一起走
        while fast.next:
            fast,slow = fast.next,slow.next
        
        # 3. 让慢指针next指向下一个节点
        slow.next =slow.next.next
        return dummy.next
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值