第五章 - 高频考题(中等)
1906. 查询差绝对值的最小值
0019. 删除链表的倒数第 N 个节点

题目地址(19. 删除链表的倒数第 N 个节点)

题目描述

1
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
2
3
示例:
4
5
给定一个链表: 1->2->3->4->5, 和 n = 2.
6
7
当删除了倒数第二个节点后,链表变为 1->2->3->5.
8
说明:
9
10
给定的 n 保证是有效的。
11
12
进阶:
13
14
你能尝试使用一趟扫描实现吗?
Copied!

前置知识

  • 链表
  • 双指针

公司

  • 阿里
  • 百度
  • 腾讯
  • 字节

思路

这里我们可以使用双指针算法,不妨设为指针 A 和 指针 B。指针 A 先移动 n 次, 指针 B 再开始移动。当 A 到达 null 的时候, 指针 B 的位置正好是倒数第 n。这个时候将 B 的指针指向 B 的下下个指针即可完成删除工作。
算法:
  • 设置虚拟节点 dummyHead 指向 head(简化判断,使得头结点不需要特殊判断)
  • 设定双指针 p 和 q,初始都指向虚拟节点 dummyHead
  • 移动 q,直到 p 与 q 之间相隔的元素个数为 n
  • 同时移动 p 与 q,直到 q 指向的为 NULL
  • 将 p 的下一个节点指向下下个节点
19.removeNthNodeFromEndOfList

关键点解析

  1. 1.
    链表这种数据结构的特点和使用
  2. 2.
    使用双指针
  3. 3.
    使用一个 dummyHead 简化操作

代码

代码支持: JS, Java,CPP
Javascript Code:
1
/**
2
* @param {ListNode} head
3
* @param {number} n
4
* @return {ListNode}
5
*/
6
var removeNthFromEnd = function (head, n) {
7
let i = -1;
8
const noop = {
9
next: null,
10
};
11
12
const dummyHead = new ListNode(); // 增加一个dummyHead 简化操作
13
dummyHead.next = head;
14
15
let currentP1 = dummyHead;
16
let currentP2 = dummyHead;
17
18
while (currentP1) {
19
if (i === n) {
20
currentP2 = currentP2.next;
21
}
22
23
if (i !== n) {
24
i++;
25
}
26
27
currentP1 = currentP1.next;
28
}
29
30
currentP2.next = ((currentP2 || noop).next || noop).next;
31
32
return dummyHead.next;
33
};
Copied!
Java Code:
1
/**
2
* Definition for singly-linked list.
3
* public class ListNode {
4
* int val;
5
* ListNode next;
6
* ListNode(int x) { val = x; }
7
* }
8
*/
9
class Solution {
10
public ListNode removeNthFromEnd(ListNode head, int n) {
11
TreeNode dummy = new TreeNode(0);
12
dummy.next = head;
13
TreeNode first = dummy;
14
TreeNode second = dummy;
15
16
if (int i=0; i<=n; i++) {
17
first = first.next;
18
}
19
20
while (first != null) {
21
first = first.next;
22
second = second.next;
23
}
24
25
second.next = second.next.next;
26
27
return dummy.next;
28
}
29
}
Copied!
CPP Code:
1
class Solution {
2
public:
3
ListNode* removeNthFromEnd(ListNode* head, int n) {
4
ListNode *p = head, *q = head;
5
while (n--) q = q->next;
6
if (!q) {
7
head = head->next;
8
delete p;
9
return head;
10
}
11
while (q->next) p = p->next, q = q->next;
12
q = p->next;
13
p->next = q->next;
14
delete q;
15
return head;
16
}
17
};
Copied!
复杂度分析
  • 时间复杂度:$O(N)$
  • 空间复杂度:$O(1)$
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。