链表反转问题 1:整体反转

leetcode 206:反转链表

难度等级:简单 ⭐

迭代

定义前后两个指针,遍历的时候将后面指针的 next 赋值给前面,形成反向链表。

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def reverseList(self, head: ListNode) -> ListNode:
        pre, cur = None, head
        while cur:
            cur.next, pre, cur = pre, cur, cur.next
        return pre  #  从这里开始输出

对于 Python 这样的写法,下面图示可以很好地说明问题。

cur.next, pre, cur = pre, cur, cur.next

链表反转问题 1:整体反转_第1张图片

python 语言的强大之处在于多重赋值,翻译成其他语言就是下面这样:

 tmp = cur.next
 cur.next = pre
 pre = cur
 cur = tmp

cur.next 取代临时变量 tmp ,其余顺序保持不变,就形成了同时赋值。

注意顺序一定要:先改变 next 的指向,然后移动指针。

建议学 Python 的都能掌握这种赋值方式,对于复杂的链表转向问题很有帮助。

递归
def reverseList(self, head: ListNode) -> ListNode:
    if not head or not head.next:
        return head
    a = head.next
    p = self.reverseList(a)
    a.next = head
    head.next = None
    return p

递归解法不太容易明白,咱们先看结束条件:只有一个结点是就将其返回。
递归是从内层返回到外层的,可以结合图来看, 当前结点 head 指代的就是当前结点,而 head 的下一个结点 a 是已经反转好的,并且 a 结点已经是反转后的最末尾结点。自然会使用 a.next = head,把 head 也连上去。
不要忘了 a 是通过 head 找到的,反转之后就不应该再找到,所以将 head 指向 None

待到最终递归结束后,会发现当初第一个结点指向为 None,这就是为何代码中 head.next 要赋值为 None,而不是别的。

递归相比迭代要难以理解,下面两个图是递归过程中的两个中间状态,可以结合代码好好理解一下。
链表反转问题 1:整体反转_第2张图片链表反转问题 1:整体反转_第3张图片

迭代与递归的比较

迭代很容易理解,遍历完链表就出来结果了。
递归在该程序中,就相当于遍历完链表,才找到递归重点,然后一层层带着结果回到上层。直觉看起来是从右到左,也就是逆序来了一遍。

你可能感兴趣的:(leetcode,链表,指针,数据结构,python)