「leetcode」206-反转链表

337 阅读2分钟

链表第二篇,前篇可见: 「leetcode」141-环形链表(两种解法&JS实现的注意点)

题目

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

示例 1:

image.png 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re…

思路分析

  • 下面有个官方提示:链表可以选用迭代或递归方式完成反转

迭代方法

  • 一开始我的思路是遍历一遍链表,然后将其一一反转,但是这样需要O(2N)的时间复杂度,所以 ×
  • 那么我们可以边遍历边反转,也即是遍历一遍,将当前的指针的next指向上一个,就可以了。这样只需要O(N)的时间复杂度。
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    if (!head || !head.next) return head
    let cur = head // 当前
    let last = null // 上一个节点的地址
    let origin = null // 原本的指向
    let endPoint = null // 最终输出的链表的起点
    // 这里的origin可以不用闭包,用临时变量解决
    while (cur) {
      origin = cur.next
      cur.next = last
      last = cur
      cur = origin
    }
    endPoint = last
    return endPoint
};
  • 这里要额外注意返回的是什么,不要真的把链表当数组处理。应该返回的是链表的最后一个节点的指针。

递归方法

  • 递归这里我看了官方解法,按照自己的理解来描述一下。
  • 首先要做一个递归解法的话,返回的应该是自己的调用,这样才能保证到达最后一个节点。
  • 思路很简单描述,例如 4->5->null,那么反转的话就是让4<-5,也就是4的next(5)的next由null变为4,为了防止死循环,再让4的next先解开为null,4成为最后一个节点(fake),再重复进行这个过程。
  • 但是这里为什么最终返回的是 newHead 而不是 head, 我也不是很清楚,如果有知道的大佬希望可以在评论区讨论下,先感谢了。
// 递归解法
var reverseList = function(head) {
    if (!head || !head.next) return head
    // 递归传入下一个节点,目的是为了到达最后一个节点
    let newHead = reverseList(head.next)
    head.next.next = head
    head.next = null
    return newHead
};