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

1.LeetCode24. 两两交换链表中的节点

题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/
文章链接:https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
视频链接:https://www.bilibili.com/video/BV1YT411g7br

在这里插入图片描述

思路:
本题的关键有两点:
①转移顺序
在这里插入图片描述
图片来自代码随想录
②返回的是虚拟头结点的next节点,即:dump.next
虚拟头结点始终指向head节点。
解释如下:
在第一次循环中,虚拟头结点被cur指针引用,cur.next=second,就将虚拟头结点的next指向了second,这样虚拟头结点指向了新的头结点。而第一次循环后,cur=first,即cur指向了新的一个节点first,cur也就不会对虚拟头结点进行操作了。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dump = new ListNode(0);//虚拟头结点
        dump.next=head;
        ListNode cur=dump;
        ListNode first;
        ListNode second;
        ListNode temp;
        while(cur.next!=null&&cur.next.next!=null){
            temp=cur.next.next.next;
            first=cur.next;
            second=cur.next.next;

            cur.next=second;
            second.next=first;
            first.next=temp;
            cur=first;
        }

        return dump.next;

    }
}

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

题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
文章链接:https://programmercarl.com/0019.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B9.html
视频链接:https://www.bilibili.com/video/BV1vW4y1U7Gf

在这里插入图片描述

思路:
使用快慢指针的方式。fast快指针和slow慢指针,两者保证一定的间隔,然后整体移动,当fast等于null时,slow恰好处在需要处理的节点位置。这里的重点是要确定处理哪个节点,以及间隔应该是多少合适。
①因为是删除节点,我们需要获取到待删除节点的前驱节点,也就是slow最终要指向的节点;
②为了保证最终slow能指向待删除节点的前驱节点,fast和slow之间要间隔n个节点。这样,当fast等于null时,slow处在倒数第n+1个节点,即倒数第n个节点的前驱节点处。

解法:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    // public ListNode removeNthFromEnd(ListNode head, int n) {
    //     int size=0;
    //     ListNode cur=head;
    //     while(cur!=null){
    //         size++;
    //         cur=cur.next;
    //     }
    //     int index=size-n;
    //     if(index<0||index>=size) return null;

    //     ListNode dump=new ListNode(0);//虚拟头结点
    //     dump.next=head;
    //     ListNode pre=dump;
    //     for(int i=0;i< index;i++){
    //         pre=pre.next;
    //     }

    //     pre.next=pre.next.next;
    //     return dump.next;

    // }

    //双指针
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dump = new ListNode(0);
        dump.next=head;

        ListNode fast=dump;
        ListNode slow=dump;

        while(n--!=0&&fast!=null){
            fast=fast.next;
        }

        fast=fast.next;//为了保证在fast和slow两个指针整体移动时,当fast等于null时,slow能够指向删除节点的前一个节点

        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
        }

        slow.next=slow.next.next;
        return dump.next;

    }
}

代码分析:
重点是如何要确定fast的起始位置,以保证与slow之间间隔n个节点。代码如下:

ListNode fast=dump;
ListNode slow=dump;
while(n--!=0&&fast!=null){
     fast=fast.next;
}
fast=fast.next;//为了保证在fast和slow两个指针整体移动时,当fast等于null时,slow能够指向删除节点的前一个节点

3.面试题 02.07. 链表相交

题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/
文章链接:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html

在这里插入图片描述

思路:
解题的关键是要抹除两个链表之间的长度差。有两种方式解答:
①方式1. 获取两个链表的长度,并计算两个链表长度差,然后让长链表的头结点的指针往前移动长度差个节点,使得两个链表的起始指针位于同一起跑线上,之后两个指针同时往前移动,比较节点是否相同;
②方式2. 使用双指针形式。两个指针A和B分别在两个链表上同时移动,A指向短链表,B指向长链表,当短链表的A指针为null时,其指向长链表的头结点,此时B指针移动了两个链表相同长度的那部分距离,剩下的就是长度差值;此时A和B都在长链表上,当A和B继续同时移动时,两者移动的距离就是两个链表的长度差。当B为null时,其指向短链表的头节点,此时A在长链表上移动了长度差,剩下的长度是两个链表相同长度的那部分距离,即此时长短链表长度差被抹除,A和B处在同一起跑线上。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    //     int sizeA=0;
    //     int sizeB=0;
    //     ListNode curA=headA;
    //     ListNode curB=headB;
    //     while(curA!=null){
    //         sizeA++;
    //         curA=curA.next;
    //     }

    //     while(curB!=null){
    //         sizeB++;
    //         curB=curB.next;
    //     }     

    //     ListNode startA=headA;
    //     ListNode startB=headB;
    //     int n=sizeA-sizeB;
    //     if(n>=0){
    //         while(n--!=0){
    //            startA=startA.next; 
    //         }
    //     }else{
    //         while(n++!=0){
    //             startB=startB.next;
    //         }
    //     }

    //     while(startA!=null&&startB!=null&&startA!=startB){
    //         startA=startA.next;
    //         startB=startB.next;
    //     }

    //     return startA;
    // }

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1=headA;
        ListNode p2=headB;

        while(p1!=p2){
            if(p1==null){
                p1=headB;
            }else{
                p1=p1.next;
            }

            if(p2==null){
                p2=headA;
            }else{
                p2=p2.next;
            }
        }

        return p1;

    }
}

代码解析:
链表相交,是两个节点相同,不是值相同

4.LeetCode 142.环形链表II

题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/
文章链接:https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html
视频链接:https://www.bilibili.com/video/BV1if4y1d7ob

在这里插入图片描述

思路:
解题关键为:确定相遇点,由相遇点出发确定入口点。
①使用快慢指针找到相遇点,其中快指针fast每次移动两个节点,慢指针slow每次移动一个节点,节点相同处为相遇点;
②找到相遇点后,定义两个指针,一个指针从头结点出发,一个指针从相遇点出发,每次移动一个节点,节点相同处为环入口。

解法:
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;

        while(fast!=null&&fast.next!=null){//若为null,说明没有环;否则有环。
            fast=fast.next.next;
            slow=slow.next;

            if(fast==slow){//相遇点
                ListNode p1=head;
                ListNode p2=fast;

                while(p1!=p2){//未到入口点
                    p1=p1.next;
                    p2=p2.next;
                }
                return p1;
            }
        }

        return null;
        
    }
}
  • 24
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值