leetcode 24 19 142 160 链表刷题笔记

86 阅读3分钟

- leetcode 24 两两交换链表中的节点 medium

题目链接: leetcode.com/problems/sw…

思路: 链表题画图很关键,根据画图尝试在2个节点以及前节点的指向改变逻辑,并提前保存后节点方便循环下次执行。

代码:

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummynode = new ListNode(-1, head);
        ListNode cur = head;
        ListNode pre = dummynode;
        while (cur != null && cur.next != null) {
            ListNode post = cur.next;
            pre.next = cur.next;
            cur.next = cur.next.next;
            post.next = cur;
            pre = cur;
            cur = post;
            cur = cur.next.next;
        }
        return dummynode.next;
    }
}

提交报错 (2):

第1次: Found cycle, 原因是没画图所以思路不清晰,链表指向改变的逻辑不清晰导致环, 另外没有想清楚循环操作的范围。

第2次: 第2对开始不翻转,原因是缺失了将指针挪到下一轮循环的操作。

- leetcode 19 删除链表的倒数第N个节点 medium

题目链接: leetcode.com/problems/re…

思路: 快慢指针,快慢指针的间隔应该为n。保证慢指针最终停留在要删除的节点的前一个,方便删除操作。另也需要合适地探寻链表的结尾。

代码:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummynode = new ListNode(-1, head);
        ListNode fast = dummynode;
        ListNode slow = dummynode;
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return dummynode.next;
    }
}

提交报错 (2):

第1次: 循环int i 未提供初始值,

第2次: 快慢指针从head开始导致错误,及时单独考虑了只有一个节点的情况而添加快慢指针同步向前条件,当前节点也要为null。使用dummynode要考虑不同方面,一是特殊对待只为方便保存链表头并返回,二是可以加入到整个链表当中加入到循环操作的逻辑中。

- leetcode 142 环形链表II medium

题目链接: leetcode.com/problems/li…

思路: 快慢指针,链表题需要画图,使用给定常规case发现规律。题目的目标是找到环的起点,则假设链表起点到环的起点距离为x。设定快指针每次走2步,慢指针每次走1步,则快指针在经过n圈移动后环内必有相交点,设环起点到相交点为y,相交点 到环起点为z。则有等式2(x+y)=n(y+z)2(x+y) = n(y+z),根据等式可推导出x=(n1)y+nzx=(n-1)y+n*z, y=(n1)y+nzy=(n-1)y+n*z, 则x=zx=z。在发现相交点后,把相交点和起始点同时移动,在相等时会找到环起始位置。

代码:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode start = head;
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (slow == fast) {
                while (start != fast) {
                    start = start.next;
                    fast = fast.next;                    
                }
                return start;
            }
        }
        return null;
    }
}

提交报错 (2):

第1次: 错误比较(slow.val == fast.val), 要比较的并非值,而是节点是否相等,即(slow == fast)

第2次: 没有考虑到只有2个点成环的特殊情况,需要根据具体test case报错改进。

- leetcode 160 链表相交 easy

题目链接: leetcode.com/problems/li…

思路: 用两个指针分别从两个链表的表头开始移动,寻找节点相等的位置,如果相等则返回任意指针,如果不相等则向前移动,如果遇到链表尾部则使指针总另外的另外一个链表的表头开始移动,如此循环则一定会解决链表长度不平衡的问题。

代码:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
       ListNode listA = headA;
       ListNode listB = headB;
       if (headA == null || headB == null) {
           return null;
       }
       while (listA != listB) {
           listA = listA == null ? headB : listA.next;
           listB = listB == null ? headA : listB.next;
       }
       return listA;
    }
}

提交报错 (1):

第1次: 边界值问题,没有考虑到两链表都为空的情况。

疑问点,求解答!!! ❓❓如果两个链表都不为空又不相交好像没有考虑到,不知道怎么理解?