LeetCode每日一题

127 阅读2分钟

Day1:LeetCode19.删除链表的倒数第N个节点

题目描述

image.png

解题思路

第一块代码是错误做法,设置了三个指针former和latter用于找倒数第n个节点,node用于删除latter节点的后一个节点,但虚拟节点node是不变的,因为需要用于返回整个链表; 出错的地方在于把虚拟节点移动到了latter节点的前一位,但实际上虚拟节点不能移动,因为要用于返回整个链表。 正确做法应该是把latter作为需要删除的倒数第n个节点的前一个节点,即需要其初始化时指向虚拟节点,然后通过latter.next=latter.next.next来实现删除倒数第n个节点。 最后返回虚拟节点所指向的下一个节点的位置,即返回新链表。

//之前的错误做法,设置了三个指针,former和latter用于找倒数第n个节点,node用于删除latter节点的后一个节点,但虚拟节点node是不变的,因为需要用于返回整个链表
// var removeNthFromEnd = function(head, n) {
//             let former = head;
//             let latter = head;
//             let node = new ListNode(-1);
//             node.next = head;
//             for (i = 0; i < n; i++) {
//                 former = former.next;
//             }
//             while (former !== null) {
//                 former = former.next;
//                 latter = latter.next;
//                 node = node.next;
//             }
//             node.next = node.next.next;
//             return node.next;
//         }

var removeNthFromEnd = function(head, n) { 
            const node = new ListNode(-1,head); //node节点值为-1,指针指向head节点
            let former = head;
            let latter = node; //注意!不是latter求链表的倒数第n个节点,而是倒数第n个节点的前一个节点,便于用来删除倒数第n个节点
            for (i = 0; i < n; i++) {
                former = former.next;
            }
            while (former != null) {
                former = former.next;
                latter = latter.next;
            }
            latter.next = latter.next.next; //删除倒数第n个节点就是将指针直接指向倒数第n个节点的下一个节点
            return node.next; //返回常数的虚拟节点node,即返回新链表
        }

Day2:LeetCode143.重排链表(L0->Ln->L1->L_(n-1)->...)

题目描述

image.png

解题思路

为实现(L0->Ln->L1->L_(n-1),...),分为三步走:

(1)找到链表中间节点,注意只需找到其指针位置,不需要设置函数因为不需要返回值

(2)反转后半部分链表,需要返回反转后的头结点,为下一步链接两部分链表做准备

(3)链接两链表,这也是最容易出错的部分,主要分为以下几点需要引起重视: a.需要设置虚拟头结点,用于返回重排的链表,避免因为节点变化导致需要考虑的情况变复杂 b.两部分链表不是通过中间节点相连,可以分开单独看,画示意图上下并排 c.列举具体的数值链表,根据示意图找规律,再来写节点指针的位置变换代码

var reorderList = head => {
            //只需获取中间节点slow,不需返回值,便于下一步反转后半部分链表
            if (head === null && head.next === null) return;
            let slow = head;
            let fast = head;
            while (fast && fast.next) {
                slow = slow.next;
                fast = fast.next.next;
            }

            //链接两部分链表
            const result = new ListNode(-1); //定义虚拟头结点用于返回链表
            result.next = head;
            let node1 = head;
            let node2 = reverse(slow); //反转后半部分链表
            while (node2.next) {
                const next1 = node1.next;
                const next2 = node2.next;
                node1.next = node2;
                node2.next = next1;
                node1 = next1;
                node2 = next2;
            }

            return result.next;

            //反转后半部分链表
            function reverse(node) {
                let cur = node;
                let pre = null;
                while (cur) {
                    const next = cur.next;
                    cur.next = pre;
                    pre = cur;
                    cur = next;
                }
                return pre;
            }
        }