反转链表:递归解法

反转整个链表

先直接上代码:

class Solution20:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head
        last = self.reverseList(head.next)
        head.next.next = head
        head.next = None

        return last

怎么理解呢?我们一行一行的来看!
首先是badcase部分,当链表为空,或者只有一个节点的时候,直接返回就可以了,也没什么好反转了!

if not head or not head.next:
   return head

最后三行就很神奇的,初次刷题是懵的状态,看了东哥的解释才回过神来。对于递归的问题,最关键的是明确递归函数的定义。在上面的函数中,reverseList表示给定一个链表,对其进行反转,并输出反转后的链表的头节点

然后来看last是个什么东西:

last = self.reverseList(head.next)

在这里插入图片描述

现在离我们想要的结果还缺把2指向1,于是我们写了:

head.next.next = head

以及把head指向空:

head.next = None

在这里插入图片描述

反转链表的前N个节点

延续上面的思路,明确递归函数的定义。在这个问题里,显然我们的递归函数需要定义为:给定一个链表和N,反转链表的前N个节点,并返回反转以后的链表的头节点。

def reverseN(self, head: Optional[ListNode], N: int) -> Optional[ListNode]:
    global successor
    if N == 1:
        successor = head.next
        return head
    tmp = self.reverseN(head.next, N-1)
    head.next.next = head
    head.next = successor

    return tmp

因为这个问题不是反转整个链表,最后head.next不再是为null啦!所以要记录一个被打断的点successor,作为head.next。其他的思路和前面一样。
在这里插入图片描述

反转链表的某一部分

代码简单的可怜:

class Solution:
    def reverseN(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        """反转链表的前N个节点,并返回反转之后的链表的头节点"""
        successor = None
        if n == 1:
            successor = head.next
            return head
        last = self.reverTopN(head.next, n-1)
        head.next.next = head
        head.next = successor

        return last

    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        if left == 1:
            return reverseN(head, left, right)
        head.next = self.reverseBetween(head.next, left-1, right-1)

        return head

第一个函数就不解释了,就是反转链表的前N个节点的函数。

badcase也很好理解,如果left=1的话,相当于反转前right个节点,直接调用self.reverseN就可以了。

if left == 1:
	return self.reverseN(head, left, right)

那如果left != 1呢,如果我们把head.next作为被反转的主体,left和right相应的都要-1才能对得上,直接调用就行了。

参考资料

  1. 《labuladong的算法小抄》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值