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

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

  • 24. 两两交换链表中的节点
  • 19. 删除链表的倒数第 N 个结点
  • 面试题 02.07. 链表相交
  • 142. 环形链表 II

我新建的个人博客,欢迎访问:hmilzy.github.io


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

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

方法一:同样设置虚拟头结点。这里需要操作的结点数很多,数四个分别为 cur、firstNode、secondNode、temp,判断循环结束的条件需要注意一下,避免出现空指针异常

/**
 * 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(0);
        dummyhead.next = head;
        ListNode cur = dummyhead;
        ListNode temp;
        ListNode firstNode;
        ListNode secondNode;

        while(cur.next != null && cur.next.next != null){
            temp = cur.next.next.next;
            firstNode = cur.next;
            secondNode = cur.next.next;

            cur.next = secondNode;
            secondNode.next = firstNode;
            firstNode.next = temp;

            cur = firstNode;
        }
        return dummyhead.next;
    }
}

方法二:递归法(此处有点难以理解,需要多画图吧)

/**
 * 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) {

        //递归法
        if(head == null || head.next == null){
            return head;
        }
        
        ListNode temp = head.next;
        ListNode newNode = swapPairs(temp.next);

        temp.next = head;
        head.next = newNode;

        return temp;
    }
}

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

题目链接: 删除链表的倒数第 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) {

        //第一种做法当然是先遍历链表,找出链表长度。然后再遍历到倒数第n个结点附近,进行删除
        ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        ListNode cur = dummyhead;
        int size = 0;
        while(cur.next != null){
            cur = cur.next;
            size++;
        }

        //找到要删除结点的前一个结点
        cur = dummyhead;
        for(int i = 0; i < size - n; i++){
            cur = cur.next;
        }
        cur.next = cur.next.next;

        return dummyhead.next;
    }
}

第二个方法:倒数第n个结点,可以从头节点开始,找到一个大小为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(0);
        dummyhead.next = head;

        ListNode fast = dummyhead;
        ListNode slow = dummyhead;

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

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

        return dummyhead.next;
    }
}

面试题 02.07. 链表相交

题目链接: 链表相交
参考题解:思路十分巧妙

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

142. 环形链表 II

题目链接: 环形链表 II
具体思路可以看卡哥文章,很清晰。

要判断是否成环。这里采用快慢指针的思路,满指针走一步,快指针走两步,看是否会相遇。

成环之后,要返回进入环的位置。可以先找到相遇点位置,让一个指针从头结点开始走,另一个指针从相遇点开始走,最后一定相遇,且相遇的地方就是环入口。

/**
 * 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) {

        ListNode fast = head;
        ListNode slow = head;
        //找到相遇点
        while (true) {
            if (fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;
        }
        //一个从头结点出发,一个从相遇点出发。总会相遇
        fast = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;


        /*
        ListNode fast = head;
        ListNode slow = 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;
        */
    }
}

你可能感兴趣的:(代码随想录算法训练营,链表,算法,数据结构)