删除链表的第N个结点
题目:
思路:
我们先从简单一点的题目入手,将原标题改为,寻找链表中倒数第N个结点。
方法一:
我们先求得链表的长度len,如果要寻找倒数第N个结点,即寻找正数第(len-N+1)个结点。这个方法需要我们遍历两次链表,一次用于求链表的长度
ListNode ptr=head,pre_ptr=head;
int length=0;
while(ptr!=null)
{
length++;
ptr=ptr.next;
}
,一次用于寻找第(len-N+1)个结点
while(i<length-n)
{
pre_ptr=ptr;
ptr=ptr.next;
i++;
}
pre_ptr.next=ptr.next;
方法二:
如果我们只想遍历一次链表,我们可以使用双指针法。
我们假设有A、B两地的距离是200m,甲、乙两个人一开始都在A地,如果我们要求甲要走到离B地50m距离的地方。
那我们可以先让乙从A地出发走50m,而甲原地不动,这样他们两个人之间的距离为50m,然后让两个人以同样的速度在相同时间里向B移动,当乙到达B点是,两人同时停下,甲最终停下的位置就是距离B50m的位置。
同样的道理,我们定义两个指针,一个先向前移动n个结点,然后两个指针再同时向前移动。慢的那个所指向的结点就是我们要找的。
再将这道题稍微修改一下就是我们的题目了,如果我们不只是要找到这个结点,我们还要将它删除,那么我们还要多定义一个指针,指向目标结点的前一个结点,方便删除目标结点。
以下是代码的实现:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode ptr1=head,ptr2=head;
ListNode pre_ptr1=head;
int count=0;
while(count<n)
{
ptr2=ptr2.next;
count++;
}
while(ptr2==null)
{
//说明删除的是第一个元素
head=ptr1.next;
return head;
}
while(ptr2!=null)
{
ptr2=ptr2.next;
pre_ptr1=ptr1;
ptr1=ptr1.next;
}
pre_ptr1.next=ptr1.next;
return head;
}
注意:当删除的结点是第一个结点的时候应该作为一种特殊情况进行处理,因为目标结点前面没有结点。所以我们在处理链表的时候会有一个头结点,里面用于存储长度或其他有用信息,而不用于存储链表的元素。