Q10-LeetCode206- 反转链表

61 阅读1分钟

一 实现思路

1 思维层面

1 递归法:

  • S1 明确递归函数语义
  • S2 在语义基础上 画出 数据结构示意图(一般是分成 已处理部分 + 未处理部分)
  • S3 对当前节点进行操作,从而使其符合函数功能定义

2 迭代法:

2.1 在解决链表问题时,应该培养"单节点职责"的思维模式

  • 每次操作只关注 当前节点要做的事情,其他节点的处理留给下一次循环

2.2 画图辅助思考

原始链表: 1  ->   2 ->  3 ->  null

第一步: null  <-  1    2  ->  3 ->  null

第二步: null  <-  1 <-  2   3 ->  null

第N步: null  <-  1 <-  2 <-  3

2 参考实现

01-官方实现

二 代码实现

方法1: 递归法 时间复杂度O(n) 空间复杂度 O(n)

// 返回 反转后的链表头节点
function reverseList(head) {
  if (!head || !head.next) return head;
  // 函数功能语义: 反转了以head为头节点的链表,并返回了反转后的新头节点 newHead
  let newHead = reverseList(head.next);

  // 注意此时head.next,还指向着 反转后的尾节点, 即 curHead--> newTail <--yyy <-- newHead
  // 所以想要反转包含curHead的整个链表,通过newTail(即 head.next)就很简单了

  // 这一句就相当于 const newTail = head.next; newTail.next = head;
  head.next.next = head
 
  // 让curHead的next断开指向newTail,从而避免循环链表
  head.next = null;

  // 返回 新的头结点即可
  return newHead;
}

方法2: 迭代法 时间复杂度O(n) 空间复杂度 O(1)

function reverseList(head) {
  let pre = null, cur = head
  while (cur) {
    const willNext = cur.next
    // 修改当前指针指向前一个
    cur.next = pre
    // 移动pre和cur到下一个节点
    pre = cur
    cur = willNext
  }
  // 到最后pre指向的就是 原链表的最后一个节点
  return pre
}