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

day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

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

用虚拟头结点,这样会方便很多。
本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。
题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode cur = new ListNode();
        ListNode listNode1 = head;
        ListNode listNode2 = new ListNode();
        cur.next=listNode1;
        ListNode head2=head.next;
        while (cur.next!= null && cur.next.next!= null){
            listNode2.next=cur.next.next;
            cur.next.next=listNode2.next.next;
            listNode2.next.next=cur.next;
            cur.next=cur.next.next;
            if(listNode2.next.next.next!=null&&listNode2.next.next.next.next!=null)
            listNode2.next.next.next=listNode2.next.next.next.next;
        }
        return  head2;
    }
}
 if(listNode2.next.next.next!=null&&listNode2.next.next.next.next!=null)
            listNode2.next.next.next=listNode2.next.next.next.next;

这个是为了使链表能够接上,提前指向下下节点

代码随想录算法训练营十期day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II_第1张图片

19.删除链表的倒数第N个节点(双指针)

双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head.next==null && n==1){
            return head.next;
        }
        ListNode listNode = new ListNode();
        ListNode cur= new ListNode();
        cur.next=head;
        ListNode res= new ListNode();
        res.next=head;
        listNode.next=head;
        int p=0;
        int q=0;
        while (cur.next.next!= null){
            if(q-p !=n){
                cur.next=cur.next.next;
                q++;
            }else {
                cur.next=cur.next.next;
                listNode.next=listNode.next.next;
            }
        }
        if(q-p!=n){
            res.next= res.next.next;
        }
        listNode.next.next=listNode.next.next.next;
        return    res.next;
    }

双指针妙用,一趟就行

代码随想录算法训练营十期day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II_第2张图片

if(q-p!=n){
            res.next= res.next.next;
        }

注意一种情况 就是删除头结点

面试题 02.07. 链表相交 (数学知识)

题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p=headA;
        ListNode q=headB;
        if(p==null||q==null)
            return null;
        int count=0;
        while (p!=q && count<3){
            if(p.next==null)
            {
                p=headB;
                count++;
            }else {
                p=p.next;
            }
            if(q.next==null)
            {
                q=headA;
                count++;
            }else {
                q=q.next;
            }
        }
        return count>3?null:p;
    }
}

两个数组 最后必然相同,知道这个就方便了
[4,1,8,4,5 5,0,1,8,4,5]

[5,0,1,8,4,5 4,1,8,4,5]

142.环形链表II (数学知识)

算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/

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

判断链表是否有环

可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

如果有环,如何找到这个环的入口

ListNode index1=fast;
ListNode index2=head;
while (index2!=index1){
       index2=index2.next;
        index1=index1.next;
}

代码随想录算法训练营十期day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II_第3张图片

总结

滑动窗口

代码随想录算法训练营十期day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II_第4张图片

代码随想录算法训练营十期day4|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II_第5张图片

双指针

什么是双指针(对撞指针、快慢指针)

双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。

换言之,双指针法充分使用了数组有序这一特征,从而在某些情况下能够简化一些运算。

对撞指针

对撞指针是指在有序数组中,将指向最左侧的索引定义为左指针(left),最右侧的定义为右指针(right),然后从两头向中间进行数组遍历。

对撞数组适用于有序数组,也就是说当你遇到题目给定有序数组时,应该第一时间想到用对撞指针解题。

两数之和

二分法

快慢指针

快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针(fast)慢指针(slow),两个指针以不同的策略移动,直到两个指针的值相等(或其他特殊条件)为止,如fast每次增长两个,slow每次增长一个。

以LeetCode 141.环形链表为例,,判断给定链表中是否存在环,可以定义快慢两个指针,快指针每次增长一个,而慢指针每次增长两个,最后两个指针指向节点的值相等,则说明有环。就好像一个环形跑道上有一快一慢两个运动员赛跑,如果时间足够长,跑地快的运动员一定会赶上慢的运动员。

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