前端必刷算法题:“反转链表”

185 阅读2分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

题目

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

示例 1:

image.png

输入:head = [1,2,3,4,5]

输出:[5,4,3,2,1]

示例 2:

image.png

输入:head = [1,2]

输出:[2,1]

示例 3:

输入:head = []

输出:[]  

提示:

链表中节点的数目范围是 [0, 5000]

-5000 <= Node.val <= 5000  

解法一:迭代

思路:

让当前的next 等于当前的pre

让pre等于当前的cur

假设链表为1 - 2- 3- null ,我们想要把它改成这样:null - 1- 2-3. 在遍历链表时,将当前节点的next指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。

复杂度分析

  • 时间复杂度:O(n)O(n),其中 nn 是链表的长度。需要遍历链表一次。
  • 空间复杂度:O(1)O(1)。
var reverseList = function(head) {
let cur=head
let pre=null
while(cur){
    const next = cur.next;
    cur.next = pre ;
    pre = cur;
    cur = next;
}
return pre
};

解法二:递归

思路:

使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 retret

此后,每次函数在返回的过程中,让当前结点的下一个结点的 nextnext 指针指向当前节点。

同时让当前结点的 nextnext 指针指向 NULLNULL ,从而实现从链表尾部开始的局部反转

当递归函数全部出栈后,链表反转完成。


var reverseList = function(head) {
    let prev = null;
    let curr = head;
    while (curr) {
        const next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
};

时间复杂度:O(n)O(n),其中 nn 是链表的长度。需要对链表的每个节点进行反转操作。

空间复杂度:O(n)O(n),其中 nn 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 nn 层。