代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、160.链表相交、142.环形链表II

56 阅读2分钟

24.两两交换链表中的节点

19.删除链表的倒数第N个节点

160.链表相交

142.环形链表II

24.两两交换链表中的节点

  • 我的思路:

    1. 拆成第基数个和第偶数个执行对应的行为:难以处理奇数的行为,需要暂存第 i+3 个节点
    2. 两个两个为一组进行指针操作:如何处理非偶数个的情况
    3. 串珠:出现环形节点
  • 我思路的缺陷:没能正确拆解交换的步骤,不是4个节点为一组,而是3个节点

var swapPairs = function(head) {
    const dummyHead = new ListNode(-1, head);
    let p = dummyHead;
    let next = p.next;
    let next2 = p.next?.next?.next;

    while (p.next && p.next?.next) {
        p.next = next.next;
        p.next.next = next;
        p.next.next.next = next2;

        p = p.next.next;
        next = p.next;
        next2 = p.next?.next?.next;
    }

    return dummyHead.next;
};

19.删除链表的倒数第N个节点

  • 我的思路:
    1. 暴力解法:遍历两遍,先得长度再得从哪里删除
    2. 只遍历一次:删除倒数第n个 = 使用双指针的话,右指针为空时,左指针刚好就是要删除的元素!
var removeNthFromEnd = function(head, n) {
    const dummyHead = new ListNode(-1, head);
    let p0 = dummyHead, p1 = dummyHead;

    for (let i=0; i<n+1; i++) {
        p1 = p1.next;
    }

    while (p1) {
        p0 = p0.next;
        p1 = p1.next;
    }

    p0.next = p0.next.next;
    return dummyHead.next;
};

160.链表相交

  • 我的思路:走对方的路,相同时即为相交。设相交后的部分为x,则len(A)=a+x,len(B)=b+x,走a+x+b和走b+x+a,如相交则此时节点一定相同。
  • 过程缺陷:忽略各种思路成立条件和边界情况,如二次赋值的机会只有一次,且可能a===b直接无需二次赋值;其中一方直接为空;头节点就直接相交。
  • 对比末尾对齐再找相同节点的方法,我的方法感觉不那么直接且要考虑的情况更多了..
var getIntersectionNode = function(headA, headB) {
    if (!headA && headB)    return null;
    if (headA && !headB)    return null;
    if (headA === headB)    return headA;

    let p0 = headA, p1 = headB;
    let ahasChanged = 0;
    let bhasChanged = 0;    
    while (p0 && p1 && p0 !== p1 && ahasChanged < 2 && bhasChanged < 2) {
        let p0HasChanged = false, p1HasChanged = false;
        if (!p0.next) {
            p0 = headB;
            ahasChanged++;
            p0HasChanged = true;
        }
        if (!p1.next) {
            p1 = headA;
            bhasChanged++;
            p1HasChanged = true;
        }

        if(!p0HasChanged) p0 = p0.next;
        if(!p1HasChanged) p1 = p1.next;
    }

    return ahasChanged < 2 && bhasChanged < 2 ? p0 : null;
};

142.环形链表II

  • 我的思路:找交点的主要问题在于不知道链表长度,要是知道并能知道相遇长度m,两个指针相差m一定能相遇->噢快慢指针,它们走的步数可以不一样!->诶但相遇点不一定在入口诶:(->(看题解吧...)->从相遇点到交点,推导太妙了:)
var detectCycle = function(head) {
    let p0 = head, p1 = head;

    let meetNode = null;
    while (p1 && p1.next) {
        p0 = p0.next;
        p1 = p1.next.next;
        if (p0 === p1) {
            meetNode = p1;
            break;
        }
    }

    if (!meetNode)  return null;

    p0 = head;
    p1 = meetNode;
    while (p0 !== p1) {
        p0 = p0.next;
        p1 = p1.next;
    }

    return p0;
};