前端算法面试必刷题系列[6]

291 阅读3分钟

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

12. 删除链表的倒数第N个节点 (remove-nth-node-from-end-of-list)

标签

  • linkList链表
  • prehead
  • 快慢指针
  • 中等

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

删除链表中倒数第 n 个结点。

相关知识

在对链表进行操作时,一种常用的技巧是添加一个仿头节点(prehead),它的 next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了

例如,在本题中,如果我们要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了仿头节点,那么头节点的前驱节点就是仿头节点本身,此时我们就只需要考虑通用的情况即可。

基本思路

需要删除链表中的倒数第 n 个节点,我们需要知道的就是倒数第 n+1 个节点,然后删除删除倒数第 n+1 节点的后继节点即可

使用快慢指针:设置 2 个指针,一个指针距离前一个指针 n 个距离同时移动 2 个指针,2 个指针都移动相同的距离。当一个指针移动到了终点,那么前一个指针就是倒数第 n 个节点了。

步骤如下:

  1. fast 快指针提前走 n+1
  2. slow 指针指向当前距离 fast 倒数第 n 个节点, 初始为 head 然后, fast 、 slow 同步向前走,直到 fast.nextnull
  3. 此时,fast 为最后一个节点,slow 就是倒数第 n+1 个节点,此时问题就变更为删除链表中的 slow 的后继节点
preHead
 |
[ ]  ->  [ 1 ]  ->  [ 2 ]  ->  [ 3 ]  ->  [ 4 ]  ->  [ 5 ] -> null
 |                               |                         
slow =>                       fast =>
fast/slow距离为 n,并同时右移,fast 到底,那么 slow 的下一个就是倒数第 n 个节点

写法实现

/**
 * 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) {
  // 建立 preHead
  let preHead = new ListNode(0)
  // prehead 是 head的前驱
  preHead.next = head
  // 建立前后指针
  let [fast, slow] = [preHead, preHead]
  // 前指针先走 n + 1 步
  for (let i = 0; i < n; i++) {
    fast = fast.next
  }
  // fast、slow 一起前进
  while(fast && fast.next) {
    fast = fast.next
    slow = slow.next
  }
  // 删除 slow 的后继节点
  slow.next = slow.next.next
  return preHead.next
}

年初二就来一题吧。

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the reiver monster,我看到就通过,暗号对不上不加哈

参考