Day04

今日任务

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

24 两两交换链表中的节点

题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/

方法一:遍历实现

思路:

Day04_第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 ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode temp = dummyHead;
        while(temp.next != null && temp.next.next != null) {
            ListNode node1 = temp.next;
            ListNode node2 = temp.next.next;
            temp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            temp = node1;
        }
        return dummyHead.next;
    }
}

 方法二:递归

目前不太理解


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

题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

关键是 找到链表的倒数的位置

思路:

  1. 两个指针,一块一慢,都指向 dummyNode
  2.  先让快指针 先走 n+1 步
  3. 然后两个指针一起移动,直到快指针走到尽头
  4. 此时 慢指针 指向的 Node 就是倒数第N个节点 的前面一个节点
  5. 然后 让 倒数第N 个节点的前节点 指向 倒数第N 个节点的 后节点
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        ListNode fast = dummyNode;
        ListNode slow = dummyNode;

        for(int i = 0; i <= n; i++) {
            fast = fast.next;
        }
        while(fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummyNode.next;
    }
}

160 链表相交

题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/

同样使双指针的问题,关键点在于,后面相交的部分长度是一致的,就要保存两个链表在后面长度是一致的时候才能开始遍历

思路:

  1. 先计算两个链表的长度,使 curA 指向的是不短的那个链表
  2. 让长的链表 先走 两个链表长度差值的长度,这样两个链表的剩余长度就保持一致
  3. 开始遍历两个链表,当指向的是同一个对象的时候,就是交点
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0, lenB = 0;
        while(curA != null) {
            lenA++;
            curA = curA.next;
        }
        while(curB != null) {
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        //使 curA 指向的链表使长的链表
        if(lenA < lenB) {
            int tmp = lenA;
            lenA = lenB;
            lenB = tmp;

            ListNode tmpNode = curA;
            curA = curB;
            curB = tmpNode;
        }
        int gap = lenA - lenB;
        while(gap-- > 0) {
            curA = curA.next;
        }
        while(curA != null) {
            if(curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }
}

 142 环形链表II

题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/

关键在于 要理解为什么一定是快的指针 从后面和 慢指针 相遇

一定是环内第一圈相遇

Day04_第2张图片

可知:x+y+z+y = 2 * (x + y)    =>  x = z;

 思路:

  1. 先理解为什么在环内,慢指针的第一圈相遇
  2. 将快指针放在头节点,慢指针依然为相遇节点
  3. 然后以同样速度,一次移动一个位置的话,就是走到环形入口相遇

代码:

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;
    }
}

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