代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表

代码随想录刷题笔记Day4–链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表

LeetCode 24. 两两交换链表中的节点

题目描述:

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]

解题思路

设定一个虚拟头节点,使得虚拟头节点的指针指向第一个节点,可以操作后面的修改过程

第一种写法

/**
 * 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 node=new ListNode(0,null);
      node.next=head;
     pre=node;
     let cur=head;
     while(cur!=null&&cur.next!=null)
     {
         pre.next=cur.next;
         cur.next=pre.next.next;
         pre.next.next=cur
         cur=cur.next;
         pre=pre.next.next;
     }
     return node.next;
};

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

题目描述:

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

示例 1:

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

解题思路

  • 双指针解题思路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mik1u9eT-1673861460221)
代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表_第1张图片

第一种写法(本人写法,先计算总数,后减去倒数的就是正数的了)

/**
 * 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 cur=head;
    let count=0;
    while(cur!=null)
    {   count++;
        cur=cur.next;
    }
 if (count === n) {
        head = head.next;
    } else {
    
    cur=head;
   for (let i = 0; i < count - n - 1; i++) {
            cur = cur.next;
        }
    cur.next=cur.next.next;}
    return head;
};

第二种写法(双指针)

/**
 * 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 res =new ListNode(0,head);
      let p=res;
      let slow=p.next;
      let fast=p.next;
      let count=1;
      for(let i=0;i<n;i++)
          {
              fast=fast.next;
              count++;
          }
    	
    if(fast==null)
        {
            p.next=slow.next;
            return res.next
        }
      while(fast.next!=null)
          {
              count++;
              slow=slow.next;
              fast=fast.next;
              p=p.next;
          }
    
      if(fast.next==null)
          {
              slow.next=slow.next.next;
          }
    return res.next;
};

面试题 02.07. 链表相交

题目描述:

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

图示两个链表在节点 c1 开始相交**:**

代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表_第2张图片

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构

示例 1:

代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表_第3张图片

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表_第4张图片

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

解题思路

代码可以写的非常简洁漂亮

  • 求长度方法可以分离出去,减少代码的耦合

    var getListLen = function(head) {
        let len = 0, cur = head;
        while(cur) {
           len++;
           cur = cur.next;
        }
        return len;
    } 
    
  • 在解决题目中,不论链表A长还是链表B长,都转换为A长,统一解决问题,不然代码冗长

          [curA,curB]=[curB,curA];
          [len1,len2]=[len2,len1];
    

写法

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

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getListLen = function(head) {
    let len = 0, cur = head;
    while(cur) {
       len++;
       cur = cur.next;
    }
    return len;
} 
var getIntersectionNode = function(headA, headB) {
    let curA=headA; let curB=headB;
    let len1=getListLen(headA);
    let len2=getListLen(headB);
    if(len1<len2)
    {
      [curA,curB]=[curB,curA];
      [len1,len2]=[len2,len1];
    }
    let i=len1-len2;
    while(i-->0)
    {
        curA=curA.next;
    }
    while(curA!=null&& curA!=curB)
    {
        curA=curA.next;
        curB=curB.next;
    }
    return curA;

};

反思:
这个题目每次我写代码都非常冗长,因为没有将一些方法分离出去,也未考虑可以统一使用认定a长来解决额外问题,使得重复的代码非常多。


LeetCode 142. 环形链表 II

题目描述:

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。xxxxxxxxxx 输入:head = [3,2,0,-4], pos = 1输出:返回索引为 1 的链表节点解释:链表中有一个环,其尾部连接到第二个节点。输入:head = [1,2,3,4]输出:[2,1,4,3]

解题思路

双指针之快慢指针:直观地来说就是当快慢指针相遇时,让其中任一个指针指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置

重要问题

  • 快指针为什么会在第一圈就找到慢指针完成相遇
  • 为什么相遇之后,慢指针(回到head)和快指针(在相遇的点)以相同速度就能找到出口?【同如何找到环形链表的第一个相遇的节点】

代码随想录刷题笔记Day4--链表之两两交换链表中的节点 删除链表的倒数第 N 个结点 链表相交 环形链表_第5张图片

第一种写法

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

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {

    let fast=head;
    let slow=head;
    while(fast!=null&&fast.next!=null)
    {
        fast=fast.next.next;
        slow=slow.next;
        if(fast==slow) {
   slow=head;
    while(fast!=slow)
    {
        slow=slow.next;
        fast=fast.next;
      }
      return slow;

        };
     }
   return null;
};

你可能感兴趣的:(链表,leetcode,数据结构)