刷题系列之206.反转链表

69 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

题目来源

leetcode.cn/problems/re…

题目介绍

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

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

题目分析

题目很短,就一个目的,把一个链表反转输出。我们应该利用双指针来分析,首先需要一个空指针指向头节点resultHead,在定义一个移动的指针moveNode,一个临时存储节点的指针tempNode。

当moveNode存在时,需要tempNode=moveNode.next先存起来,把moveHead.next赋值给resultHead,最后在把tempNode重新赋值给moveHead,这时候可以进入下一次循环了,并且这一次循环实际是moveNode.next,这时候就反转了第一个节点。

题目解答

/**
 * 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 tempNode = null, resultHead = null, moveNode = head;
    while(moveNode) {
        tempNode = moveNode.next;
        moveNode.next = resultHead;
        resultHead = moveNode;
        console.log(resultHead)
        moveNode = tempNode;
      
    }
    return resultHead;
};

这里第一次循环resultHead应该是【1】, 第二次循环从 moveNode.next = resultHead;可以这时候moveNode应该是【2,1】,下一步又通过 resultHead = moveNode;把节点重新设置给resultHead,因此第二次循环resultHead也变成了【2,1】依次类推,【3,2,1】、【4,3,2,1】、【5,4,3,2,1】循环结束,这时候reultHead的结果就是链表反转了。 image.png

官方解答

var reverseList = function(head) {
    if (head == null || head.next == null) {
        return head;
    }
    const newHead = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
};

官方的解法也有很多种,这里我主要分析下递归的解法,因为涉及到链表,所以这类题目一般用递归都可以有对应的解法。

主要就是要让最后一个结点指向倒数第二个结点,然后把最后一结点的指针域赋值为空。

核心解答

   /*
            第一轮出栈,head为5,head.next为空,返回5
            第二轮出栈,head为4,head.next为5,执行head.next.next=head也就是5.next=4,
                      把当前节点的子节点的子节点指向当前节点
                      此时链表为1->2->3->4<->5,由于4与5互相指向,所以此处要断开4.next=null
                      此时链表为1->2->3->4<-5
                      返回节点5
            第三轮出栈,head为3,head.next为4,执行head.next.next=head也就是4.next=3,
                      此时链表为1->2->3<->4<-5,由于3与4互相指向,所以此处要断开3.next=null
                      此时链表为1->2->3<-4<-5
                      返回节点5
            第四轮出栈,head为2,head.next为3,执行head.next.next=head也就是3.next=2,
                      此时链表为1->2<->3<-4<-5,由于2与3互相指向,所以此处要断开2.next=null
                      此时链表为1->2<-3<-4<-5
                      返回节点5
            第五轮出栈,head为1,head.next为2,执行head.next.next=head也就是2.next=1,
                      此时链表为1<->2<-3<-4<-5,由于1与2互相指向,所以此处要断开1.next=null
                      此时链表为1<-2<-3<-4<-5
                      返回节点5
            出栈完成,最终头节点5->4->3->2->1
         */

总结

这道题的递归确实有点抽象,得很仔细的揣摩,链表题还需要在训练,我发现还是有一定难度。