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

本文介绍了四种链表操作的解题思路:1)两两交换链表中的节点,通过画图和临时变量实现;2)删除链表的倒数第N个节点,利用快慢指针找到目标节点的前驱;3)相交链表,通过两个指针同步移动找交点;4)环形链表II,检测环并找到入口。所有方法都涉及链表结构和指针操作。
摘要由CSDN通过智能技术生成

两两交换链表中的节点

题目链接:24. 两两交换链表中的节点

解题思路:画图,弄清楚节点之间的指向改变,弄清楚循环的终止条件和需要临时保存的节点。最后确定循环中cur指针的移动。

class Solution {
    public ListNode swapPairs(ListNode head) {
        //定义虚拟头结点并指定其next指针为head
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;

        //定义一个指向当前节点的指针,初始指向虚拟头结点
        ListNode cur = dummyhead;

        //终止条件,顺序不能反,避免出现空指针
        while(cur.next != null && cur.next.next != null){
            //定义两个临时节点,用来存储第一个和第三个节点
            ListNode temp = cur.next;
            ListNode temp1 = cur.next.next.next;
            cur.next = cur.next.next;//步骤1,由虚拟头结点指向2节点
            cur.next.next = temp;//步骤2,由2节点指向1节点
            temp.next = temp1;//步骤3,由1节点指向3节点

            //移动cur指针
            cur = cur.next.next;
        }
        return dummyhead.next;
    }
}

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

题目链接:19. 删除链表的倒数第 N 个结点

解题思路:画图,利用快慢指针,先找到要删除节点的前驱节点

  1. 先让快指针移动n+1步后,让快慢指针同时移动
  2. 当快指针移动到空节点时,慢指针正好移动到要删除节点的前一个节点
  3. 让慢指针的slow.next = slow.next.next,删除该元素
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        ListNode fast = dummyhead;
        ListNode slow = dummyhead;
        
        n++;
        //先让快指针移动n+1步
        while(n-->0 && fast != null){
            fast = fast.next;
        }
        //快慢指针同时移动到快指针指到null
        while(fast != null){
            fast = fast.next;
            slow =slow.next;
        }
        //找到了要删除节点的前一个节点位置即为slow
        slow.next = slow.next.next;
        return dummyhead.next;
    }
}

相交链表

题目链接:160. 相交链表

解法一:走的长度相等时,最后相遇点即是交点

当p在A链表走到null时,从B链表开始走;

当q在B链表走到null时,从A链表开始走。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        ListNode q = headB;
        while(p != q){
            p = p != null ? p.next : headB;
            q = q != null ? q.next : headA;
        }
        return p;
    }
}

解法二:先计算两个链表的长度,将长链表先移动到和短链表相同的位置,然后判断两个节点是否相等。相等直接返回,不相等继续移动。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        // 求两个链表的长度
        int lenA = 0;
        int lenB = 0;
        while(curA != null){
            lenA++;
            curA = curA.next;
        }        
        while(curB != null){
            lenB++;
            curB = curB.next;
        }
        // 将指针重新指向头结点
        curA = headA;
        curB = headB;
        // 让curA指向的是长链表
        if(lenA < lenB){
            int tempLen = lenA;
            lenA = lenB;
            lenB = tempLen;

            ListNode tempNode = curA;
            curA = curB;
            curB = tempNode;
        }
        // 让curA移动和curB同时开始的位置
        int gap = lenA - lenB;
        while(gap-- > 0){
            curA = curA.next;
        }
        // 判断,当curA和curB相等时,直接返回
        while(curA != null){
            if(curA == curB){
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;        
    }
}

环形链表Ⅱ

题目链接:142. 环形链表 II

主要考察两个知识点:

  1. 判断链表是否有环?定义两个快慢指针,快指针每次走两个单位,慢指针每次走一个单位,如果快慢指针相遇,说明有环。
  2. 如果有环,如何找到环的入口?快慢指针相遇后,一个指向相遇点,一个指向链表头结点,同时移动,两个指针相遇的点即是环的入口。
public class Solution {
    public ListNode detectCycle(ListNode head) {
        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(index1 != index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值