一、问题描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
二、解题思路
最直接的想法就是使用两次扫描,第一次扫描计算链表中的元素个数,第二次扫描通过计算倒数第n个元素的下标,得到这个元素,通过前一个元素的next指针改变即可完成。
一次扫描的思路就是首先在链表中扫描n个元素,此时的head就是已经扫描的元素中的倒数第n个,用一个指针来表示。接下来再向后扫描,每扫描一位,就将这个指针往后移动一位,直到扫描完整个链表,这个指针指向的元素就是整个链表的倒数第n位。
三、代码
方法一:两次扫描
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)return null;
int sum=0;
ListNode cur=head;
while(cur!=null){
sum++;
cur=cur.next;
}
if(sum==n)return head.next;
int pre=sum-n-1;
cur=head;
for(int i=0;i<pre;i++){
cur=cur.next;
}
cur.next=cur.next.next;
return head;
}
}
方法二:一次扫描
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)return null;
int sum=1;
ListNode cur=head;
ListNode res=head;
while(sum<n+1){
cur=cur.next;
sum++;
}
if(cur==null)return head.next;//说明删除头节点
//此时head到cur一共n+1个元素,即head是当前遍历的元素所有元素中倒数第n+1个元素
while(cur.next!=null){
res=res.next;
cur=cur.next;
}
res.next=res.next.next;
return head;
}
}
四、结果
执行时间 | 0ms | 100% |
---|---|---|
消耗内存 | 37.8M | 5.43% |