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

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

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

 主要考察对链表的复杂操作,难度不大

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode dummy = new ListNode(-1 ,head);
        ListNode front = head.next;
        ListNode mid = head;
        ListNode tail = dummy;
        while (front != null){
            ListNode temp = front.next;
            tail.next = front;
            front.next = mid;
            mid.next = temp;
            tail = mid;
            mid = temp;
            if (mid == null) break;
            front =mid.next;

        }
        return dummy.next;
    }
}

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

使用双指针,两者间距n个节点,则当快的指针到达末尾后,慢指针刚好指向倒数第N个节点,由于是删除操作,使用前驱节点来进行查找

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1, head);
        ListNode pre = dummy;
        ListNode fast = head;
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while (fast != null){
            fast = fast.next;
            pre = pre.next;
        }
        pre.next = pre.next.next;
        return dummy.next;
    }
}

面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

 

 比较容易想到,将长链表的队头指针先向后移动两条链表的差值个节点,则此时若AB存在交点,则两个队头指针到交点的距离相同,此时只要将两个链表头指针同时向后移动,找到相同的节点之后返回即可,若不存在交点,则两指针同时为空时都为null,符合题目要求

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode dummyA = new ListNode(-1, headA);
        ListNode dummyB= new ListNode(-1, headB);
        int count = 1;
        while (headA != null){
            count++;
            headA = headA.next;
        }
        while (headB != null){
            count--;
            headB = headB.next;
        }
        headA = dummyA.next;
        headB = dummyB.next;
        if (count < 1){
            count = 1 - count;
            while (count-- != 0){
                headB = headB.next;
            }
        }else {
            while (count-- != 1){
                headA = headA.next;
            }
        }
        while (headA != headB){
            headA = headA.next;
            headB = headB.next;
        }


        return headA;
    }
}

 142.环形链表II

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

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

循环链表

 

思路:这题首先需要解决的是判断链表是否为环。解决链表题目时,多指针是我们常会选用的方法,双指针法能否解决本题,我们先思考。

        当两个指针都进入到环形区域后,继续向后遍历,指针会一直在链表里“绕圈”。而如果两个指针的速度,即前进的步长不同,最终一定会出现一个指针追上另一个指针的情况,追上时可能两个指针恰好重合,也可能快指针直接超过了慢指针。超过的情况是我们不喜欢的,因为不好判断。我们喜欢刚好重合,一旦重合,就可以确定链表为环形,因为快指针追上了慢的指针。

        这个时候两个指针在环形区域的情况就简化成了追击问题,快指针速度每比慢指针速度多一,则每次移动时,快指针和慢指针的距离减一,那快指针的速度只要比慢指针速度刚好多一,则可以保证在追击时,快指针一定会和慢指针重合(移动一次距离减一),一定可以将距离减为0,即重合。好了,判断是否为环的问题就完全解决了。接下来看看如何找到入环节点。

 

 图中标出了三个点,链表头节点,入环节点,相遇节点。我们很容易可以得出,相遇时:

慢指针走过了:a1+a2

快指针走过了:a1 + a2 + a3 + a2

因为慢指针速度为1,快指针速度为2,所以有

2x(a1+a2) = a1 + a2 + a3 + a2

解得a1 = a3

由于a1长度等于a3,所以此时如果我们将一个节点从相遇节点向后遍历,一个节点从头节点向后遍历,则相遇点即为入环点

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) {
                break;
            }
        }
        if (fast == null || slow != fast) {
            return null;
        }
        fast = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }

        return fast;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值