代码随想录day4 -链表

代码随想录day4

两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
在这里插入图片描述

思路

模拟链表交换节点操作
递归实现

class Solution {
    // 递归实现
    public ListNode swapPairs(ListNode head) {
        if(head == null ||  head.next == null)
            return head;
        ListNode next = head.next;
        ListNode nextNode = swapPairs(next.next);
        next.next = head;
        head.next = nextNode;
        return next;
    }
}

借助于虚拟头结点模拟三步交换操作
在这里插入图片描述

class Solution {
    // 模拟交换实现
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode cur = dummy;
        while(cur.next != null && cur.next.next != null){
        	// 保存中间变量
            ListNode tmp = cur.next.next.next;
            ListNode first = cur.next;
            ListNode second = cur.next.next;
            // 三步操作
            cur.next = second;
            second.next = first;
            first.next = tmp;
            cur = first;
        }
        return dummy.next;
    }
}

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

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
在这里插入图片描述

思路

先得出链表长度,再去寻找需要删除的节点 – 遍历查找

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode cur = head;
        int size = 0;
        while(cur != null){
            size++;
            cur = cur.next;
        }
        // 是否删除头结点
        if(size == n)
            return head.next;
        cur = head;
        // 找到前一个节点
        for(int i = 0;i < size - n - 1;i++){
            cur = cur.next;
        }
        ListNode nextnext = cur.next.next;
        cur.next = nextnext;
        return head;
    }
}

双指针思想:双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

class Solution {
    // 双指针
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 借助虚拟头节点
        ListNode dummy = new ListNode(-1,head);
        ListNode slow = dummy,fast = dummy;
        // 让快指针先走N+1步,这样让slow节点位于需要删除节点的前一个
        for(int i = 0;i < n + 1;i++){
            fast = fast.next;
        }
        // 找到需要删除的前一个节点
        while(fast != null){
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}

注意:删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点

环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

思路

快慢指针思想:先判断是否有环。
若有环,经过数学追击思维分析,可知:
双指针第二次相遇:

令 fast 重新指向链表头部节点。此时 f=0,s=nb。
slow 和 fast 同时每轮向前走 111 步。
当 fast 指针走到 f=a步时,slow 指针走到 s=a+nb	步。此时两指针重合,并同时指向链表环入口,返回 slow 指向的节点即可。
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head,fast =head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            // 第一次相遇
            if(slow == fast){
                fast = head;
                while(slow != fast){
                    slow = slow.next;
                    fast = fast.next;
                }
                return fast;
            }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值