Day04 链表 leetcode力扣24.两两交换链表中的节点(利用虚拟头结点)19.删除链表的倒数第 N 个结点(灵活使用快慢指针)

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

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

先看清题目,是两两交换链表中的节点,不是交换节点的值,并且是原地交换

理解完题目的意思,可以看出这是两两分组进行交换,那么只需要找出每次交换的规律即可

与反转链表相似,这里可以利用虚拟头节点来便于操作
我们知道交换两个节点的步骤,假设虚拟头结点为dummy,交换node1和node2节点(节点位置如下:虚拟头结点=》node1=》node2)

交换过程

1、node1.next = node2.next(断开1,2连接,node1指向node2后面元素 )

2、dummy.next = node2 (连接虚拟头结点和node2)

3、node2.next = node (连接node2和node1)

通过这三步,完成node1和node2的节点交换

但这只是一对节点交换,而这里是对整个链表两两交换,因此需要确定下次虚拟节点位置,通过分析,可以确定下次虚拟节点为这次交换后node1的位置
dummy = node1

下次交换时的node1,node2也是同样的dummy.next 和dummy.next.next

循环上述过程便完成了两两交换的过程

最后需要确定循环终止条件:dummy.next和dummy.next.next 都同时存在

两个难点:

1、确定交换过程,利用虚拟头结点

2、确定循环终止条件
解决这两个问题,代码就显而易见了

var swapPairs = function (head) {
  let dummy = new ListNode(0, head); // 创建虚拟头节点
  let current = dummy;

  while (current.next !== null && current.next.next !== null) {
    let first = current.next;       // 第一节点
    let second = current.next.next; // 第二节点

    // 交换节点
    first.next = second.next;
    second.next = first;
    current.next = second;

    // 移动到下一对节点
    current = first;
  }

  return dummy.next;
};


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


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

当需要返回头结点的时候,利用虚拟头结点进行返回

这里灵活使用快慢指针,求倒数第几个就让快指针提前跑几格

再让快慢指针一起跑,直到快指针到达链表末尾

删除操作:slow.next = slow.next.next

完整代码

var removeNthFromEnd = function (head, n) {
  // 创建虚拟头节点以简化删除头节点的处理
  let dummy = new ListNode(0, head);
  let fast = dummy, slow = dummy;

  // 快指针先移动 n 步
  for (let i = 0; i < n; i++) {
    fast = fast.next;
  }

  // 快慢指针同时移动,直到快指针到达链表末尾
  while (fast.next !== null) {
    fast = fast.next;
    slow = slow.next;
  }

  // 删除目标节点
  slow.next = slow.next.next;

  // 返回链表的新头节点
  return dummy.next;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值