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

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

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/swap-nodes-in-pairs/description/
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
  • 视频讲解icon-default.png?t=N7T8https://www.bilibili.com/video/BV1YT411g7br/?vd_source=af4853e80f89e28094a5fe1e220d9062
  • 简单图示:

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

  • 题解:
/**
 * 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 int size(ListNode head){
        // 如果传入空链表,直接返回链表大小为0
        if(head == null){
            return 0;
        }
        // 链表可以保证至少头结点不为空,长度至少为1
        ListNode cur = head;
        int size = 1;
        while(cur.next != null){
            cur = cur.next;
            size++;
        }
        return size;
    }
    public ListNode swapPairs(ListNode head) {
        ListNode dummyhead = new ListNode();
        dummyhead.next = head;

        ListNode current = dummyhead;

        if(size(head) % 2 == 0){
            // 如果链表长度为偶数
            while(current.next != null){
                ListNode temp = current.next;
                ListNode temp1 = current.next.next.next;
                current.next = current.next.next;
                current.next.next = temp;
                temp.next = temp1;
                current = current.next.next;
            }
        }else{
            // 如果链表长度为奇数
            while(current.next.next != null){
                ListNode temp = current.next;
                ListNode temp1 = current.next.next.next;
                current.next = current.next.next;
                current.next.next = temp;
                temp.next = temp1;
                current = current.next.next;
            }
        }

        return dummyhead.next;
    }
}

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

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/0019.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B9.html
  • 视频讲解icon-default.png?t=N7T8https://www.bilibili.com/video/BV1vW4y1U7Gf/?vd_source=af4853e80f89e28094a5fe1e220d9062
  • 简单图示:

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

  • 题解(快慢指针解法):
/**
 * 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();
        dummyhead.next = head;
        ListNode fast = dummyhead;
        ListNode low = dummyhead;
        // 为了保证low移动到待删除目标结点的前驱结点
        n++ ;
        // 将fast移动n+1步,(从fast往回数第n个,要把low停在倒数第n个结点的前驱结点)
        // 若n>链表长度,则fast停在尾结点后驱null
        while(n != 0 && fast != null){
            fast = fast.next;
            n--;
        }
        // fast和low同时后移,直到fast移到最后的null
        while(fast != null){
            fast = fast.next;
            low = low.next;
        }
        // 此时,low.next为倒数第n个结点
        low.next = low.next.next;
        return dummyhead.next;
    }
}

 面试题 02.07. 链表相交

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/?envType=list&envId=t7YY2L76
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html
  • 题解1简单图示:

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

  • 题解1(借鉴了大佬的题解,优雅,实在是优雅):
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // 我走过你走的路 —— 我们终将彼此相遇
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA != curB){
            curA = curA==null ? headB : curA.next;
            curB = curB==null ? headA : curB.next;
        }
        return curA;
    }
}
  • 题解(自己写的,但是系统显示超时,Emm感觉思路没问题但是就是超时,望大佬指正) :
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // 得到传入链表的长度
    public int size(ListNode head){
        // 如果传入链表为空,直接返回0
        if(head == null){
            return 0;
        }
        // 此时至少链表不为空
        int size = 1;
        ListNode cur = head;
        while(cur.next != null){
            cur = cur.next;
            size++;
        }
        return size;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int result = size(headA) - size(headB);
        // 当链表A长度>=链表B长度时
        if(result >= 0){
            // 将两个链表末端对齐
            while(result != 0 && curA.next != null){
                curA = curA.next;
                result--;
            }
            while(curA != null || curB != null){
                // 当A、B指针均未走到末尾向后搜索时
                // 遇到两个指针相等(即两个结点相同)
                if(curA == curB){
                    return curA;
                }
            }
            // 若无交点,返回null
            return null;
        }else{
            // 当B链表长度>A链表长度时
            // 将两个链表末端对齐
            while(result != 0 && curB.next != null){
                curB = curB.next;
                result++;
            }
            while(curA != null || curB != null){
                // 当A、B指针均未走到末尾向后搜索时
                // 遇到两个指针相等(即两个结点相同)
                if(curA == curB){
                    return curB;
                }
            }
            // 若无交点,返回null
            return null;
        }
    }
}

 142.环形链表II

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/?envType=list&envId=t7YY2L76
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html
  • 视频讲解icon-default.png?t=N7T8https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=af4853e80f89e28094a5fe1e220d9062
  • 数学推导:
        tips:需要注意的点是:经过推导,将环拉直,不难得出low在进入环之后,走完一圈之前必然被fast追上过,所以设low为x+y。

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

  • 题解(数学推导是重点):
/**
 * 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 low = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            low = low.next;
            // 遇到环,快慢指针相遇
            if(fast == low){
                ListNode cur1 = fast;
                ListNode cur2 = head;
                while(cur1 != cur2){
                    cur1 = cur1.next;
                    cur2 = cur2.next;
                }
                // cur1/cur2相遇点即为环入口
                return cur1;
            }
        }
        // fast走完未遇到环,说明链表无环,返回null
        return null;
    }
}

你可能感兴趣的:(代码随想录训练营一刷,算法,链表,java)