在面试中,链表相关题目非常常见,今天我们来分析一道高频面试题:Remove Nth Node From End of List。
题目描述
给定一个链表的头节点 head,请删除链表中倒数第 n 个节点,并返回链表的头节点。
举例说明
- 输入 :
head = [1,2,3,4,5], n = 2 - 输出 :
[1,2,3,5]
- 输入 :
head = [1], n = 1 - 输出 :
[]
- 输入 :
head = [1,2], n = 1 - 输出 :
[1]
约束
- 链表节点总数
sz满足1 <= sz <= 30 - 每个节点的值
0 <= Node.val <= 100 1 <= n <= sz
进阶:只遍历一次链表能否解决?
解法一:数组辅助法(O(n) 空间)
最直接的思路是:
- 在遍历链表时,用一个数组记录每个节点的编号和指针。
- 遍历完成后,根据数组索引定位到倒数第
n个节点,访问其前驱和后继指针,断开连接即可。
- 时间复杂度:O(n)
- 空间复杂度:O(n)
这种方法实现简单,但需要辅助空间,面试官可能会追问有没有更优化的解法。
解法二:双指针法 + 虚拟头结点 dummy(O(1) 空间,O(n) 时间)
双指针法能够只遍历一次链表:
- 设置
a和b两个指针,它们初始都从链表的头节点出发。首先让b先向后移动n步(或 dummy 节点后移动n+1步)。 - 之后
a和b同步向后移动,直到b指向链表结尾(b->next == null)。 - 此时,
a指向要删除节点的前驱节点,直接修改a->next指针即可断开目标节点。 - 返回
dummy->next作为新链表头。
使用 dummy 节点的好处
dummy的next指向head。- 所有删除操作和边界情况(删除头节点)都变得一致,无需特殊处理。
小结
- 数组法空间复杂度高,但思路简单。
- 双指针 + dummy 节点,不仅实现更优,还能应对所有删除情况。
- 推荐面试中使用双指针和 dummy 节点的通用写法,提高代码健壮性。
如果你有链表相关更多问题,或想要代码实现,可以留言交流!