一日一练: 反转链表

132 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

如果链表只有两个节点?

image.png

如果链表只有两个节点的话:只需要将节点1的next指针指向null(第一次反转),然后将节点2的next指向节点1(第二次反转)即可

// 若直接改变节点1的next指向,会导致丢失 节点2的引用,所以先保存对节点2的引用
let nextNode = head.next
// 节点1 指向null
head.next = null
// 节点2 指向 节点1
nextNode.next = head

这样,上面两个节点的反转就完成了。

扩展到多节点

虽然是多节点链表,但是在操作的时候每次都只能反转两个节点。所以多节点反转操作其实是每两个节点操作的重复操作。这里最重要的是对pre节点的处理:

  1. 对两个节点处理时,首先将headnext指向null,然后将head.next指向了head
  2. 如果标识next引用的节点pre,那么第一次反转时pre = null; head.next = pre
  3. 第二次反转时:pre = head; nextNode.next = pre;

从上面的2,3条可以看出重复的规则就是不断改变当前要反转的节点(cur)和上一个已反转的节点(pre)

function reverseList(head: ListNode | null): ListNode | null {
    // 第一次为null
    let pre = null
    // 第一个要反转的为头节点
    let cur = head
    while(cur) {
        // 先记录下一个节点,防止反转之后节点丢失
        let next = cur.next
        // 指向上一个节点,完成反转
        cur.next = pre
        // 当前操作节点 变成 下一个要被引用的节点
        pre = cur
        // 处理缓存的下一个节点
        cur = next
    }
    // 当cur为null时,节点反转完成,pre中保存最后一个反转的节点,直接返回
    return pre
};