给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
思路:
先遍历一次链表,求出链表的长度,再根据长度和n找到第n-1个结点,并跳过第n个结点。写的时候没有在最前面加上一个哑结点(可以免去一些边界条件,比如长度为一和删除第一个结点)
/**
* Definition for singly-linked list.
* public class ListNode {
* public int val;
* public ListNode next;
* public ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode RemoveNthFromEnd(ListNode head, int n)
{
ListNode temp=head;
int length=1;
while(temp.next!=null)
{
length++;
temp=temp.next;
}
if(length==1&&n==1)
return null;
if(n==1)
{
temp=head;
for(int i=1;i<length-n;i++)
{
temp=temp.next;
}
temp.next=null;
}
else if(n==length)
{
head=head.next;
}
else
{
temp=head;
for(int i=1;i<length-n;i++)
{
temp=temp.next;
}
temp.next=temp.next.next;
}
return head;
}
}
时间复杂度:O(n) 空间复杂度:O(1)
进阶: 一次扫描解决
双指针:先用一个指针向前n+1步,这样两个指针直接会间隔n个结点,然后再让两个指针同时往后,当一个指针到达链表末尾时,另一个指针正好在n-1处,再跳过第n个结点即可。
/**
* Definition for singly-linked list.
* public class ListNode {
* public int val;
* public ListNode next;
* public ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode RemoveNthFromEnd(ListNode head, int n)
{
ListNode phead=new ListNode(0);
phead.next=head;
ListNode first=phead;
ListNode second=phead;
for(int i=0;i<=n;i++)
{
first=first.next;
}
while(first!=null)
{
first=first.next;
second=second.next;
}
second.next=second.next.next;
return phead.next;
}
}
时间复杂度:O(n) 空间复杂度:O(1)