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

60 阅读2分钟

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

递归两两交换

class Solution {
    // 定义:输入以head开头的单链表,将这个单链表中的每两个元素翻转,返回翻转后的链表头节点
    public ListNode swapPairs(ListNode head) {
        // base case
        if(head == null || head.next == null){
            return head;
        }

        ListNode first = head;
        ListNode second = head.next;
        ListNode others = head.next.next;

        // 先把前两个元素翻转
        second.next = first;
        // 利用递归定义,将剩下的链表节点两两翻转,接到后面
        first.next = swapPairs(others);
        // 整个链表都翻转了,返回新的头节点
        return second;
    }
}

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

快慢指针先指dummy,快指针先走n + 1步,然后快慢指针一起一步一步往后走,直到快指针到链表尾,此时慢指针指向的是倒数第N个节点的前一个节点,然后进行删除操作。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1, head);
        ListNode fast = dummy;
        ListNode slow = dummy;


        for(int i = 0; i < n + 1; i++){
            if(fast == null)return head;
            fast = fast.next;
        }

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

        if(slow.next != null){
            slow.next = slow.next.next;
        }
        
        return dummy.next;
    }
}

LeetCode 面试题 02.07. 链表相交

分别建立一个指向A头和B头的节点,走到各自链表结尾的时候,交换到另一个链表的头,如果两链表有交点,则会在交点相交,则返回。如果两链表无交点,则会在链表尾相交,然后返回null。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        /** 分别建立一个指向A头和B头的节点,走到各自链表结尾的时候,交换到另一个链表的头,如果两链表有交点,则会在交点相交,则返回。如果两链表无交点,则会在链表尾相交,然后返回null */
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA != curB){
            curA = curA != null ? curA.next : headB;
            curB = curB != null ? curB.next : headA;
        }
        return curA;
    }
}

LeetCode 142.环形链表II

快慢指针判断链表有环,快慢指针第一次相遇时,将其中一个指针重置到链表头,然后两个指针一起一步一步next,再次相遇时则是环的入口。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast, slow;
        fast = slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow)break;
        }

        if(fast == null || fast.next == null){
            // fast遇到空指针说明没有环
            return null;
        }

        // 重新指向头节点
        slow = head;

        // 快慢指针同步前进,再次相交时就是环入口
        while(slow != fast){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}