LeetCode 206:反转链表

123 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

LeetCode 206:反转链表

题目描述

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

解题思路

思路一:递归

思路如下:
用递归函数不断反转当前节点head的后继节点next;
分解:

  1. 使用递归函数,一直递归到链表的最后一个节点,该节点就是反转后的头节点,记作 newHead .
  2. 此后,每次函数在返回的过程中,让当前结点的下一个节点的 next 指针指向当前节点。
  3. 同时让当前节点的 next 指针指向 null ,从而实现从链表尾部开始的局部反转
  4. 当递归函数全部出栈后,链表反转完成。
var reverseList = function (head) {
  if (head === null || head.next === null) { // 边界情况
    return head;
  }
  const newHead = reverseList(head.next);
  head.next.next = head;  // 让后面一个节点指向前一个节点
  head.next = null; // 将前一个节点的next置为空
  return newHead;
};

时间复杂度: O(n)  ,其中 n 为链表的长度

空间复杂度: O(n),其中 n 为链表的长度

思路二:迭代

  1. 准备prev,curr,next三个指针(next其实是一个临时存储使用的变量);

  2. 在遍历的过程中,让当前指针curr.next指向前一个指针prev;

  3. 不断让prev,curr,next向后移动,直到curr为null(边界条件)

实现代码如下:

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function (head) {
  var prev = null,
    curr = head,
    next = null;
  while (curr != null) {
    next = curr.next;
    curr.next = prev;
    prev = curr;
    curr = next;
    // ES6的解构
    // [prev.next, prev, curr] = [prev, curr, curr.next]
  }
  return prev;
};

时间复杂度: O(n)  ,其中 n 为链表的长度

空间复杂度: O(1);
小结:
反转链表的核心代码如下:

next = curr.next;
curr.next = prev;
prev = curr;
curr = next;

其中prev节点的next指向curr, curr是当前节点, next其实是一个临时存储使用的变量;
或者使用ES6的解构语法 [prev.next, prev, curr] = [prev, curr, curr.next]

参考资料

206. 反转链表 - 力扣(LeetCode) (leetcode-cn.com)