LeetCode刷题日记之链表

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

题目描述

在这里插入图片描述

解题思路

在这里插入图片描述
先保存当前节点的下一个节点和下下下个节点(也就是 1和3节点),再将当前节点的下一个节点指向2节点,2节点的下一个节点指向1节点,1节点的下一个节点指向3节点

var swapPairs = function(head) {
     let preHead = new ListNode() // 虚拟头节点

     preHead.next = head;
     let cur = preHead;
     while(cur.next&&cur.next.next){ // 保证cur节点之后一定有两个节点,如果只有一个,说明只剩一个了 不操作

       let temp1= cur.next; // 纪录第一个节点
       let temp2 = cur.next.next.next; // 记录下一轮的第一个节点

       cur.next = cur.next.next;   // 当前节点到2节点
       cur.next.next = temp1;  // 2节点到1节点索引
       cur.next.next.next = temp2  // 1节点到3节点

       cur = cur.next.next // 当前节点后移两位

     }
    
    return preHead.next

};

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

题目描述

在这里插入图片描述

解题思路

思考:要删除一个节点需要从当前节点的前一个节点开始操作,让其下一个节点直接指向下下个节点,这样就相当于删除了当前节点。 本题可以使用双指针来解决,我们假设链表长度为k,那么让快指针先走n+1步,然后让快慢指针同时向后移动,当快指针到链表尾部时,慢指针移动的距离为,k-n-1,其下一个节点刚好为倒数第n个节点。所以可以很简单的写出一下代码:

var removeNthFromEnd = function(head, n) {
    let preHead = new ListNode(0,head)
   let fast = slow = preHead
   while(n -- && fast!==null){ // n -- 是先取值再计算,while执行 n + 1次
       fast = fast.next
   }
   while(fast&&fast.next){
       slow =slow.next
       fast = fast.next
   }
   slow.next = slow.next.next
   return preHead.next
};

3.链表相交

题目描述

在这里插入图片描述

解题思路

本题解题思路很巧妙,可以从数学上面分析,假设两个链表有交点,A链表在交点前面的长度为PA,B链表在交点前的节点长度为PB,交点后得节点长度为PC,让两个链表同时从头开始往后走,当A链表走到头后,让其指向B链表的头节点,B链表走到头后也指向A链表头节点,两个链表一定在链表的交点相遇。
(A走过路径长度LA = PA+PC+PB,B走过的路径长度为LB = PB + PC + PB , LA == LB)
···
var getIntersectionNode = function(headA, headB) {
let pA = new ListNode(0,headA);
let pB = new ListNode(0,headB)

while(pA!=pB){
    pA = pA ? pA.next:headB
    pB = pB?pB.next:headA;
}

return pA

};
···

4环形链表2

题目描述

在这里插入图片描述

解题思路

本题其实可以使用hash表来实现,从头结点开始,将每个节点的值添加进入hash表,当某个节点第二次出现时,该节点一定是环形链表的起点。

var detectCycle = function(head) {
    // hash表
    let set = new Set()
    while(head){
        if(set.has(head)) {
            return head
        } 
           set.add(head)
           head = head.next;
        
    }
    return null

}

除此之外,还可以使用双指针,快指针每次走两步,慢指针每次走一步,快慢指针会在环中相遇,利用数学推导可知,从相遇节点到环起点的距离就是从头节点到环起点的距离。

let fast = head
    let slow = head;
    while(fast != null && fast.next != null){ // 没有环会直接退出
        slow = slow.next; // 快慢指针 如果有环则一定会在环内相遇 数学推导
        fast = fast.next.next
        if(slow === fast) { // 快慢指针相遇 数学推导  从相遇节点到开始到 环起点和 头节点到起点的节点数一致
           let index1 = head;
           let index2 = slow;
           while(index1 != index2){
              index1 = index1.next
              index2 = index2.next
              
           }
           return index1
        }
    }
    return null

猜你喜欢

转载自blog.csdn.net/Salange1/article/details/128269858