算法练习day4

59 阅读2分钟

一、两两交换链表中的节点

问题要点

要清晰多个指针的意义,其中temp用来判断和指向后面的两个节点,然后实现两两交换


/**
 * 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) {
    let dummyHead = new ListNode(0, head)
    let temp = dummyHead // 指向后面的两个需要交换的节点
    while(temp.next && temp.next.next) {
        let pre = temp.next
        let cur = temp.next.next
        pre.next = cur.next
        cur.next = pre
        temp.next = cur
        temp = pre
    }
    return dummyHead.next
};

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

问题要点

思路是快慢指针,快指针先走n步,然后慢指针和快指针同步,直到快指针走到倒数第二个节点,慢指针走到目标节点的前一个节点

或者快指针先走n+1步,,然后慢指针和快指针同步,直到快指针走到最后一个节点,慢指针走到目标节点的前一个节点


/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
    let dummyHead = new ListNode(0, head)
    let fast = dummyHead
    let slow = dummyHead
    while(n-- >= 0) {
        fast = fast.next
    }
    // fast走到了最后一个节点
    // slow走到了目标节点的前一个节点
    while(fast) {
        slow = slow.next
        fast = fast.next
    }
    slow.next = slow.next.next
    return dummyHead.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(0, head)
    let fast = dummyHead
    let slow = dummyHead
    while(n--) {
        fast = fast.next
    }
    // fast走到了倒数第二个节点
    // slow走到了目标节点的前一个节点
    while(fast.next) {
        slow = slow.next
        fast = fast.next
    }
    slow.next = slow.next.next
    return dummyHead.next
};

三、链表相交

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
    if(!headA || !headB) {
        return null
    }
    let lenA = getLenth(headA)
    let lenB = getLenth(headB)
    let curA = headA, curB = headB
    if(lenA < lenB) {
        [lenA, lenB] = [lenB, lenA]; // 这个分号是必须得
        [curA, curB] = [curB, curA]
    }
    let i = lenA - lenB
    while(i--) {
        curA = curA.next
    }
    while(curA && curA !==curB){
        curA = curA.next
        curB = curB.next
    }
    return curA
    
};

function getLenth(head) {
    let size= 0
    let cur = head
    while(cur) {
        size++
        cur = cur.next
    }
    return size
}
var getIntersectionNode = function(headA, headB) {
    if(!headA || !headB) {
        return null
    }
   let curA = headA
   let curB = headB
   while(curA !== curB) {
       curA = curA === null ? headB : curA.next
       curB = curB === null ? headA : curB.next
   }
   return curA
};

四、环形链表2

问题要点

首先要判断链表是否有环,slow和fast必须同时从head开始走,fast走两步,slow走一步

数学公式计算:当fast进入环一圈后,必然在slow进入环的一圈内追上,当fast追上slow的时候,其距离环入口的距离等于从head到环入口的距离

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

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
    if(!head || !head.next) {
        return null
    }
    // slow和fast必须同时从head开始走,fast走两步,slow走一步
    let slow = head.next
    let fast = head.next.next
    while(slow !== fast) {
        if(!fast || !fast.next) {
            return null
        }
        slow = slow.next
        fast = fast.next.next
    }
    slow = head
    while(slow !== fast) {
        slow = slow.next
        fast = fast.next
    }
    return slow

};