206. 反转链表(Python)

作者: 玖月晴 | 来源:发表于2019-05-14 10:11 被阅读0次

题目

难度:★★☆☆☆
类型:链表

反转一个单链表。

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

示例

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

解答

方案1:迭代

使用迭代法反转链表需要三个临时变量:

当前结点cur:当前要处理的链表结点;

  1. 前一个结点prev:已经处理好的新链表的头结点;

  2. 临时结点tmp:用于暂存cur的下一个链表结点。

  3. 遍历链表过程中,不断进行的重复便是cur.next=prev:

prev, cur->tmp ==> prev <- cur, tmp

每一轮循环,因为有三个变量,所以需要三句话分别更新,链表方向调头工序夹在里面:

  1. 先把当前结点cur的下一个结点赋给临时结点tmp暂存;

  2. 将当前结点的连接方向调头,连接prev,cur成为新链表的头结点;

  3. prev结点更新为新链表的头结点;

  4. 将tmp中暂存的变量归还cur结点。

class Solution(object):     # 迭代
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur, prev = head, None

        while cur:
            tmp = cur.next              # 临时列表,用于暂存结果
            cur.next = prev             # 更换连接方向
            prev = cur                  # 后移
            cur = tmp                   # 后移

        return prev

方案2:递归

假设链表为:

1 -> 2 -> 3-> ... -> k-1 -> k -> k+1 -> ... -> n -> None

并且我们已经构造了函数,使得链表从k-1之后都被反转:

1 -> 2 -> 3-> ... ->k-1 -> k -> k+1 <- ... <- n

我们希望k-1的下一个结点指向k,则k.next.next=k:

1 -> 2 -> 3-> ... ->k-1 -> k <- k+1 <- ... <- n

需要注意的是,结点1的下一个结点是None,需要特殊处理,在之前操作的基础上设置k的下一个结点为None:

n -> n-1 -> ... -> k+1 \
          -> k -> None
1-> 2-> 3 -> ... ->k-1 /

class Solution(object):     # 迭代
   def reverseList(self, head):
       """
       :type head: ListNode
       :rtype: ListNode
       """
       if not head or not head.next:       # 如果输入结点是空,或只有一个结点,返回即可
           return head

       p = self.reverseList(head.next)     # 将下一个结点之后的部分逆序
       head.next.next = head               # 反转当前结点
       head.next = None                    # 设置当前结点的下一个结点为None
       return p

这里,特地为大家做了一个脚本,近距离展示一下递归是如何工作的:

def create_linked_list(nums):
    """
    创建链表
    :param nums: 输入代表里链表的数字列表
    :return: 返回创建好的链表的头结点,可以得到整个链表的所有信息
    """
    if not nums:                        # 输入空列表
        return
    head = prev = ListNode(nums[0])     # 第一个结点
    for num in nums[1:]:
        tmp = ListNode(num)             # 创建当前结点
        prev.next = tmp                 # 挂在已经创建好的链表末尾
        prev = prev.next                # 指针后移
    return head


def print_linked_list(head):
    """
    打印链表
    :param head: 要打印的链表的头结点
    :return: 结点值列表
    """
    nums = []
    while head:
        nums.append(head.val)
        head = head.next
    print(nums)
    return nums


class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution(object):   
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:       # 如果输入结点是空,或只有一个结点,返回即可
            return head

        p = self.reverseList(head.next)     # 将下一个结点之后的部分逆序
        head.next.next = head               # 反转当前结点
        head.next = None                    # 设置当前结点的下一个结点为None
        print_linked_list(p)                # 展示一下处理过程,如果不需要的话可以注释掉
        return p


if __name__ == "__main__":
    head = create_linked_list([1, 2, 3, 4, 5, 6, 7, 8, 9])
    s = Solution()
    reversed_head = s.reverseList(head)

该脚本的输出为:

[9, 8]
[9, 8, 7]
[9, 8, 7, 6]
[9, 8, 7, 6, 5]
[9, 8, 7, 6, 5, 4]
[9, 8, 7, 6, 5, 4, 3]
[9, 8, 7, 6, 5, 4, 3, 2]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

创建链表(create_linked_list)和打印链表(print_linked_list)函数源自【链表基础】

如有疑问或建议,欢迎评论区留言~

相关文章

网友评论

    本文标题:206. 反转链表(Python)

    本文链接:https://www.haomeiwen.com/subject/qkujaqtx.html