LeetCode刷题 Day04

90 阅读5分钟

LeetCode刷题 Day04

24. Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list's nodes (i.e., only nodes themselves may be changed.)

Example 1:

Input: head = [1,2,3,4]
Output: [2,1,4,3]

Example 2:

Input: head = []
Output: []

Example 3:

Input: head = [1]
Output: [1]

思考步骤:

WeChatc70f1063bd3d8bf4e337b4c6386dd9b1.png

注意要保存两个临时节点,一个是temp1 = curr.next, 另一个是temp2 = curr.next.next.next, 也就是量表中的第一和第三节点。以便于重新连接节点。

通过这个步骤,可以发现 a->b 而 a和b要断开连接的时候,存一个b的临时节点以方便新节点重新连接到b, 这会让条件清晰很多。

代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var swapPairs = function(head) {
    const dummyHead = new ListNode(null);
    dummyHead.next = head;
    let curr = dummyHead;
    
    while (curr.next && curr.next.next) {
        let temp1 = curr.next;
        let temp2 = curr.next.next.next;
        curr.next = curr.next.next;
        curr.next.next = temp1;
        curr.next.next.next = temp2;
        
        curr = curr.next.next;
    }
    
    return dummyHead.next;
};

时间复杂度: O(n), 空间复杂度: O(1)


19. Remove Nth Node From End of List

Given the head of a linked list, remove the nth node from the end of the list and return its head.

  Example 1:

Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Example 2:

Input: head = [1], n = 1
Output: []

Example 3:

Input: head = [1,2], n = 1
Output: [1]

思考步骤:

  • 典型的链表快慢指针题
  • 初始化dummyHead,以便于处理list中只有一个node的情况
  • slow和fast均从dummyHead开始起步
  • fast先走,走n + 1步,也就是让while (n-- >= 0)。
  • 为什么是 n + 1 步?只有这样才能 让slow ptr走到要删除节点的前一节点
  • 当走完 n + 1步后,让slow和fast ptr同时走, 直到fast为null
  • 通过slow.next = slow.next.next删除节点

代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
    let dummyHead = new ListNode(null);
    dummyHead.next = head;
    let slow = dummyHead;
    let fast = dummyHead;
    
    while (n-- >= 0) {
        fast = fast.next;
    }

    while (fast) {
        slow = slow.next;
        fast = fast.next;
    }
    
    slow.next = slow.next.next;
    return dummyHead.next;
};

时间复杂度: O(n) 空间复杂度: O(1)


160. Intersection of Two Linked Lists

Given the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.

For example, the following two linked lists begin to intersect at node c1:

The test cases are generated such that there are no cycles anywhere in the entire linked structure.

Note that the linked lists must retain their original structure after the function returns.

Custom Judge:

The inputs to the judge are given as follows (your program is not given these inputs):

  • intersectVal - The value of the node where the intersection occurs. This is 0 if there is no intersected node.
  • listA - The first linked list.
  • listB - The second linked list.
  • skipA - The number of nodes to skip ahead in listA (starting from the head) to get to the intersected node.
  • skipB - The number of nodes to skip ahead in listB (starting from the head) to get to the intersected node.

The judge will then create the linked structure based on these inputs and pass the two heads, headA and headB to your program. If you correctly return the intersected node, then your solution will be accepted.

  Example 1:

Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
Output: Intersected at '8'
Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect).
From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B (2nd node in A and 3rd node in B) are different node references. In other words, they point to two different locations in memory, while the nodes with value 8 in A and B (3rd node in A and 4th node in B) point to the same location in memory.

思路:

  • A + B = B + A, 当链表A到达尾部的时候通过从链表B的head重新出发来实现两个链表的链接,链表B同理
  • 因为二者行进速度相同, 这样总会到达相交点

代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
    let ptr1 = headA;
    let ptr2 = headB;
    
    while (ptr1 || ptr2) {
        
        if (!ptr1) {
            ptr1 = headB;
        } 
        
        if (!ptr2) {
            ptr2 = headA;
        } 

        if (ptr1 === ptr2) return ptr1;

        ptr1 = ptr1.next;
        ptr2 = ptr2.next;
    }
    
    return null;
};

时间复杂度: O(n) 空间复杂度: O(1)


142. Linked List Cycle II

Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.

Do not modify the linked list.

 

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

双指针套圈思路:

设: 直线位移为L, slow ptr圈内位移为X, 圈内剩余路程为Y slow ptr速度为v, fast ptr 速度为2v

v = L + X; 2v = L + X + n(X + Y); L + X = n(X + Y);

因为: 要求L的位置 所以: L = n(X + Y) - X; 因为: fast ptr至少要多走一圈才能保证和slow ptr相遇。所以可以假设n = 1。 所以: L = Y 这样就意味着 当slow和fast相遇之后,fast退回到起点 slow走完Y, fast走完L二者即可相遇

代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
    let slow = head;
    let fast = head;
    
    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
        
        if (slow === fast) break;
    }
    
    if (!fast || !fast.next) return null;
    
    fast = head;
    
    while (slow !== fast) {
        slow = slow.next;
        fast = fast.next;
    }
    
    return slow;
};

时间复杂度: O(n) 空间复杂度: O(1)