leetcode快慢指针法题目汇总

本文汇总了LeetCode中使用快慢指针法解决的链表问题,包括环形链表的检测、环的起点查找、部分链表反转和回文链表判断。通过实例解析,阐述了快慢指针法在解决这些链表问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

双指针法,分为左右指针和快慢指针两种。其中左右指针在数组中运用较多,可以和滑窗法一起进行汇总:滑窗法运用

而快慢指针一般在链表中运用较多,在反转链表和定位链表节点及链表成环等逻辑中运用比较广泛。

141. 环形链表

逻辑非常简单,只要是环形的链表,那么快慢指针早晚会遇到。
值得注意的一点是,用try…except…来进行异常判定

    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        try:
            slow = head
            fast = head.next
            while fast is not slow:
                fast = fast.next.next
                slow = slow.next
            return True
        except:
            return False

142. 环形链表 II

在上题的基础上,找到环形链表中环的起点,借用一张leetcode上的图。简单来说,由于兔子走两步,乌龟走一步,因此两者相遇时兔子走的距离是乌龟的一倍。
盗用一张leetcode上的图
2 d i s t a n c e ( t o r t o i s e ) = d i s t a n c e ( h a r e ) 2distance(tortoise) = distance(hare) 2distance(tortoise)=distance(hare) 2 ( F + a ) = F + a + b + a 2(F+a) =F+a+b+a 2(F+a)=F+a+b+a F = b F = b F=b

class Solution(object):
    def detectCycle(self, head):
        fast, slow = head, head
        while True:
            if not (fast and fast.next): return
            fast, slow = fast.next.next, slow.next
            #因此当两者相遇时,即图中的first intersection点时退出while循环
            if fast == slow: break
        #快指针重新移动到起点,两者同样的速度相遇时即为环的起点
        fast = head
        while fast != slow:
            fast, slow = fast.next, slow.next
        return fast

92. 反转链表 II

在之前的反转链表基础上,只反转一部分链表。因此可以引入两个指针分别定位需要反转链表的头和尾。中间反转链表后,和链表定位的头和尾重新连接即可。

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        if m == n:
            return head
        dum = ListNode(-1)
        #注意这一步指定链表的next
        dum.next = head
        a,c = dum,dum
        for i in range(m-1):
            a = a.next
        for i in range(n):
            c = c.next
        b = a.next
        d = c.next
        pre = b
        cur = pre.next
        while cur != d:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        a.next = c
        b.next = d
        return dum.next

另外除了双指针法之外,局部反转链表有一种递归的方式求解,也是在全局反转链表基础上的变幻,面试中如果能写出来,一定能加分不少。

class Solution(object):
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        #此函数的意义是反转链表的前n个节点
        def reverseN(head,n):
            if n == 1:return head
            last = reverseN(head.next,n-1)
            successor = head.next.next
            head.next.next = head
            head.next = successor
            return last
        if m == 1:return reverseN(head,n)
        #递归调用直到m-1等于1
        head.next = self.reverseBetween(head.next,m-1,n-1)
        return head

234. 回文链表

因为是回文链表,所以只需要反转前半部分节点并和后一半链表进行对比即可

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        rev = None
        fast = slow = head
        while fast and fast.next:
            fast = fast.next.next
            rev,rev.next,slow = slow,rev,slow.next
        
        if fast:
            slow = slow.next
        
        while rev and rev.val == slow.val:
            rev = rev.next
            slow = slow.next
        return not rev

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
要求时间复杂度和空间复杂度尽可能低

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        l,r = 0,0
        n = len(nums)
        while r < n:
            if nums[r] != 0:
                nums[l],nums[r] = nums[r],nums[l]
                l += 1
            r += 1
        return nums
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值