1、题目描述
2、题目分析
根据题目的几个示例,存在以下几种特殊情况:
【双指针思路】:
(1)第一个指针node先走 n 步;
(2)获取目标删除节点的【前一个】节点, 此时head的前一个节点pre ,跟第一个指针node, 相差 (n+1)个位置 ;
(3) 接下来两个指针,pre, node分别进行遍历,不难知道, 当node为null 时,pre刚好是目标删除节点的前一个节点;
(4)删除pre后的节点【既目标删除节点】pre.next = pre.next.next;
基础内容,链表的结构体:
class ListNode{
int val;
ListNode next;
ListNode(){}
ListNode(int val){
this.val = val;
}
ListNode(int val, ListNode next){
this.val = val;
this.next = next;
}
}
实现代码如下:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0,head);
ListNode node = head;
ListNode pre = dummy;
//第一次,节点node先走 n 步
for(int i = 0; i < n; i++){
if(node != null)
node = node.next;
else
return null;
}
//第二次,pre和node均继续走,此时pre和node相差(n+1)个位置,当node为null时,pre刚好是目标删除节点的前一个节点
while(node != null){
pre = pre.next;
node = node.next;
}
//删除pre后面的元素
pre.next = pre.next.next;
return dummy.next;
}
}
复杂度分析
-
时间复杂度:O(L),其中 L 是链表的长度。
-
空间复杂度:O(1), 无使用额外空间。