(算法)快慢指针与多指针

70 阅读1分钟

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

给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个结点后,链表变为 1->2->3->5.
说明:给定的 n 保证是有效的。

题解:

/** 
* @param {ListNode} head
* @param {number} n
* @return {ListNode} 
*/
const removeNthFromEnd = (head, n) => {
    const dummy = new ListNode();
    dummy.next = head;
    
    let fast = dummy;
    let slow = dummy;
    
    while(n !== 0){
        fast = fast.next;
        n--;
    }
    
    while(fast.next){
        fast = fast.next;
        slow = slow.next;
    }
    
    slow.next = slow.next.next;
    
    return dummy.next;
}

规则:

dummy前驱结点、快慢指针法

完全反转一个链表

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

题解:

/** 
* @param {ListNode} head
* @return {ListNode} 
*/
const reverseList = (head) => {
    let pre = null;
    let cur = head;
    
    while(cur.next){
        let next = cur.next;
        //反转指针
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    //当前cur结点为null停止循环,pre为新链表的头结点
    return pre;
}

规则:

pre、next 多指针法

局部反转一个链表

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
说明: 1 ≤ m ≤ n ≤ 链表长度。

题解:

/** 
* @param {ListNode} head
* @param {number} m
* @param {number} n
* @return {ListNode} 
*/
const reverseBetween = (head, m, n) => {
    let pre,cur,leftHead;
    const dummy = new ListNode();
    dummy.next = head;
    leftHead = dummy;
    // 找到区间前驱结点 m-1
    for(let i = 0; i < m - 1; i++){
        leftHead = leftHead.next
    }
    //记录开始结点
    let start = leftHead.next;
    pre = start;
    cur = pre.next;
    while(m < n){
        let next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
        m++;
    }
    //后继结点此时为反转后的区间的第一个结点
    leftHead.next = pre;
    //开始记录的后继结点指向cur
    start.next = cur;
    
    return dummy.next
}

规则:

dummy前驱结点、leftHead、start多指针法