这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
12. 删除链表的倒数第N个节点 (remove-nth-node-from-end-of-list)
标签
- linkList链表
- prehead
- 快慢指针
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
删除链表中倒数第 n 个结点。
相关知识
在对链表进行操作时,一种常用的技巧是添加一个仿头节点(prehead),它的 next
指针指向链表的头节点
。这样一来,我们就不需要对头节点进行特殊的判断了。
例如,在本题中,如果我们要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了仿头节点,那么头节点的前驱节点就是仿头节点本身,此时我们就只需要考虑通用的情况即可。
基本思路
需要删除链表中的倒数第 n 个节点,我们需要知道的就是倒数第 n+1 个节点,然后删除删除倒数第 n+1 节点的后继节点
即可
使用快慢指针:设置 2 个指针,一个指针距离前一个指针 n
个距离。同时移动 2 个指针,2 个指针都移动相同的距离。当一个指针移动到了终点,那么前一个指针就是倒数第 n 个节点了。
步骤如下:
- fast 快指针提前走
n+1
步 - slow 指针指向当前距离 fast 倒数第 n 个节点, 初始为 head 然后, fast 、 slow
同步向前走
,直到fast.next
为null
- 此时,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
,我看到就通过,暗号对不上不加哈