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

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

题目链接:. - 力扣(LeetCode)

思路解析:

在这道题里,最简单的方法还是需要用到之前所说的虚拟头节点的概念,因为在执行交换操作时需要涉及到四个节点,即前中后和下一个阶段的前节点。例如如果有一个五个节点的链表,

12345

那么,在执行时对于头节点来说缺少它的前节点,因此如果不使用虚拟头节点则需要单独讨论。如果使用虚拟头节点dummyHead,每次的执行顺序就是dummyHead指向2,2指向1,1指向3(即下一个操作的第一个节点),然后以此类推。注意在执行时需要用到临时变量存储节点的值,因为在改变指向的过程中其实也是在执行删除节点的操作。

/**
 * 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 dummyhead = new ListNode();
        dummyhead.next = head;
        ListNode point;
        point = dummyhead;
        ListNode firstnode;
        ListNode secondnode;
        ListNode nextlevel;
        while (point.next != null && point.next.next != null){
            firstnode = point.next;
            secondnode = point.next.next;
            nextlevel = point.next.next.next;
            point.next = secondnode;
            secondnode.next = firstnode;
            firstnode.next = nextlevel;
            point = firstnode;
        }
        return dummyhead.next;
    }
}

LeetCode 19 删除链表的倒数第n个节点

题目链接:. - 力扣(LeetCode)

思路解析:

在刚开始看的时候我的想法就是单纯的遍历出长度再解题。但解析的思路要比我的简单很多。简单的思路就是使用双指针,一快一慢,只需要让快的走n+1(n是题目给的倒数第n个节点),然后再让快慢指针同时同速走,当快指针走到null时,慢指针就到了需要删除节点的前一个节点。(注意,快指针不是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) {
        ListNode dummyhead = new ListNode();
        dummyhead.next = head;
        ListNode fast;
        ListNode slow;
        fast = dummyhead;
        slow = dummyhead;
        for (int i=0; i<=n; i++){
            fast = fast.next;
        }
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        slow.next=slow.next.next;
        return dummyhead.next;
    }
}

LeetCode 面试 02.07 链表相交

题目链接:. - 力扣(LeetCode)

思路解析:

这道题我也是看了解析思路才做出来。我开始想到了虽然交点前两个链表的节点数肯定不相同,所以可以从两个链表末尾到交点这段相同的距离找思路,但是没进行下去。这道题只需要把两个链表以尾节点对其,然后从将两个链表的指针都停在短链表的第一个节点位置,一直循环直到两个指针相同即可。

/**
 * 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 lengtha=0;
        int lengthb=0;
        ListNode pointa = headA;
        ListNode pointb = headB;
        while (pointa != null){
            lengtha++;
            pointa = pointa.next;
        }
        while (pointb != null){
            lengthb++;
            pointb = pointb.next;
        }
        pointa = headA;
        pointb = headB;
        int dif = Math.abs(lengtha-lengthb);
        if (lengtha >= lengthb){
            for (int i=0; i<dif; i++){
                pointa = pointa.next;
            }
            while (pointa != pointb){
                pointa = pointa.next;
                pointb = pointb.next;
            }
            return pointa;
        }else
        {
            for (int i=0; i<dif; i++){
                pointb = pointb.next;
            }
            while (pointa != pointb){
                pointa = pointa.next;
                pointb = pointb.next;
            }
            return pointa;
        }
    }
}

LeetCode 142 环形链表

题目链接:. - 力扣(LeetCode)

思路解析:

首先这道题是依靠快慢指针的相遇来判断链表是否存在环,但是如何找到入口处需要明白几个点。快慢指针在环里相遇后慢指针一定走不完一圈;而快指针一定走完至少一圈。(解释:因为,首先快指针的速度设置为2,慢指针的速度设置为1,当慢指针入环后,快慢指针之间距离一定小于环的长度,且快慢的速度差其实就是慢指针的速度,那么追上慢指针的时间一定小于慢指针走完整个环的时间;其次,如果快指针没有走完一整个圈,那么因为快慢指针在环里是同向移动的,快指针遇到慢指针意味着追上了慢指针,那么快指针如果没走完一个圈,意味着慢指针先入了环,因此矛盾。)

当明白以上几点后,我们就可以推导出公式,设x为头节点与入口处的路程,y为入口处和相遇点的路程,y为相遇点到入口处的路程,那么x+y为慢指针所走的全程,x+y+n(y+z)为快指针走的全程,其中n(y+z)代表的是n圈。那么快指针为慢指针的两倍可以列出来一个方程,解出来,当n=1时,x=z,那么意味着如果在相遇点和头节点分别放置两个节点,同速同时出发,一定会在入口处相遇。因此,通过这样我们就可以判断是否有环且有环时得到入口处的节点。

我的shi山代码

/**
 * 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) {
        if (head.next != null && head.next.next != null){
            ListNode fast=head.next.next;
            ListNode slow=head.next;
            while (fast != slow && fast != null){
                fast=fast.next.next;
                slow=slow.next;
            }
            if (fast == null ){
                return null;
            }
            ListNode cur1=head;
            ListNode cur2=fast;
            while (cur1 != cur2){
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
            return cur1;
            }else{
                return null;
            }
    }
}

答案

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {// 有环
                ListNode index1 = fast;
                ListNode index2 = head;
                // 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值