题目描述
删除链表的倒数第 n 个结点
给定一个链表,删除链表的倒数第 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
解题思路
暴力解:
链表的基本操作,因为是倒序,先数一遍链表长度。
快慢双指针:
快指针先走n步
随后慢指针开始走
当快指针走到末尾的时候,慢指针所指下一个节点就是要删除的节点
实现代码
class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
this.next = null;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public ListNode removeNthFromEnd(ListNode head, int n) {
// 判空
if(head == null) {
return null;
}
// 先获得长度
int len = 0;
for (ListNode cur = head; cur != null; cur = cur.next) {
len++;
}
// 特殊处理,要删除的就是头节点的情况
if(len-n == 0){
head = head.next;
return head;
}
// 正常删除
ListNode pre = head;
for (int i = 0; i <len - n - 1; i++) {
pre = pre.next;
}
pre.next = pre.next.next;
return head;
}
public ListNode fastRemoveNthFromEnd(ListNode head, int n) {
if(head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
// 快指针先走n步
for (int i = 0; i < n; i++) {
fast = fast.next;
}
// 刚好删除头节点
if(fast == null){
head = head.next;
return head;
}
// 快慢指针同时走
while(fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
时间及空间复杂度分析
两种方法时间复杂度均为O(n),空间复杂度O(1)
在leetcode的测试用例中,没体现出明显差异。当然,还是快慢指针更优。