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

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

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

用虚拟头结点,这样会方便很多。

本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。

题目链接/文章讲解/视频讲解:
代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II_第1张图片

看到题目的第一想法:

设置两个节点pre,和cur,初始时均置于虚拟头节点。然后就是移动pre和cur,自己手动画图,看如何才能进行两个节点之间的翻转了。
代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II_第2张图片
之后记得把cur节点置于pre处。

package com.second.day4;

public class SwapPairs_24 {
    public ListNode swapPairs(ListNode head) {
        if(head == null)
            return null;
        ListNode preHead = new ListNode(0); //虚拟头节点
        preHead.next = head;
        ListNode pre = preHead;
        ListNode cur = preHead;
        while(cur.next != null && cur.next.next != null) {
            ListNode temp1 = pre; //暂存pre节点
            pre = cur.next;     //pre和cur均往后移动一位
            cur = cur.next.next;
            ListNode temp2 = cur.next; //暂存cur的下一位
            //交换pre和cur指向的节点
            temp1.next = cur;
            cur.next = pre;
            pre.next = temp2;
            //交换后将cur指向pre
            cur = pre;
        }
        return preHead.next;
    }

    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        SwapPairs_24 demo = new SwapPairs_24();
        demo.swapPairs(node1);
    }
}

看完代码随想录之后的想法:

思路是一样的,嘻嘻。

自己实现过程中遇到哪些困难:

一定要画图,不然很容易搞不清楚,之后稍微debug后过的。

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

双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。

题目链接/文章讲解/视频讲解
代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II_第3张图片

看到题目的第一想法:

1.先遍历一遍链表,求出其长度
2.算出链表删除的第几个节点
3.删除节点

package com.second.day4;

public class RemoveNthFromEnd_19 {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //先遍历一遍链表,求出其长度
        ListNode cur = head;
        int length = 0;
        while(cur != null) {
            length += 1;
            cur = cur.next;
        }
        ListNode preHead = new ListNode(0);
        preHead.next = head;
        ListNode pre = preHead;
        cur = head;
        //算出链表删除的第几个节点
        length -= n;
        while(length > 0) {
            pre = cur;
            cur = cur.next;
            length -= 1;
        }
        //删除cur节点
        pre.next = cur.next;
        return preHead.next;
    }
}

看完代码随想录之后的想法:

卡哥的思路比我好,设置快慢指针,快指针先走n+1步,然后slow和fast指针再一起走,直到fast指针为空,删除slow后面那个节点。
为什么要fast先走n+1,而不是n呢?因为fast多走一步,结束循环时,slow指针指向删除节点的前一个节点。
比我的想法妙多了。

自己实现过程中遇到哪些困难:

无,嘻嘻。

面试题 02.07. 链表相交

本题没有视频讲解,大家注意 数值相同,不代表指针相同。

题目链接/文章讲解:
代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II_第4张图片

看到题目的第一想法:

1.遍历链表a,求其长度
2.遍历链表b,求其长度
3.求其长度差值diff
5.先让长链表先走diff
6.然后同时走,遇到相遇点。

package com.second.day4;

public class GetIntersectionNode_0207 {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null)
            return null;
        //遍历链表a,求其长度
        int length_A = 0;
        ListNode curA = headA;
        while(curA != null) {
            length_A += 1;
            curA = curA.next;
        }
        //遍历链表b,求其长度
        int length_B = 0;
        ListNode curB = headB;
        while(curB != null) {
            length_B += 1;
            curB = curB.next;
        }
        int diff = Math.abs(length_A - length_B);
        return length_A - length_B > 0 ? IntersectionNode(headA, headB, diff) : IntersectionNode(headB, headA, diff);
    }

    public ListNode IntersectionNode(ListNode headA, ListNode headB, int diff) {
        ListNode curA = headA;
        while(diff > 0) {
            curA = curA.next;
            diff -= 1;
        }
        ListNode curB = headB;
        while(curA != null && curB != null) {
            if(curA == curB)
                return curA;
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }
}

看完代码随想录之后的想法:

思路一样!!!nice!!!

自己实现过程中遇到哪些困难:

142. 环形链表 II

算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:
代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II_第5张图片

看到题目的第一想法:

看到这个题的时候只知道自己做过,在我看来,这个题更像是数学题,之后看了题解,没有第一次看题解那么难啦。
看完思想后直接AC

package com.second.day4;

public class DetectCycle_142 {
    public ListNode detectCycle(ListNode head) {
        ListNode preHead = new ListNode(0);
        preHead.next = head;
        //定义快慢指针
        ListNode fast = preHead;
        ListNode slow = preHead;
        while(fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            //当快慢指针相遇
            if(fast == slow) {
                //慢指针至于head
                slow = preHead;
                //slow指针和fast每次移动一位,相遇点即为环的入口
                while(slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        ListNode node3 = new ListNode(3);
        ListNode node2 = new ListNode(2);
        ListNode node0 = new ListNode(0);
        ListNode node4 = new ListNode(-4);
        node3.next = node2;
        node2.next = node0;
        node0.next = node4;
        node4.next = node2;
        DetectCycle_142 demo = new DetectCycle_142();
        demo.detectCycle(node3);
    }
}

看完代码随想录之后的想法:

卡哥真的妙!!!

自己实现过程中遇到哪些困难:

还需努力!!!

今日收获,记录一下自己的学习时长:

今天写了四个题:
24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
代码:1.5h
博客:1h
不积跬步无以至千里,不积小流无以成江海。继续努力。

你可能感兴趣的:(代码随想录,链表,算法,数据结构)