删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
总结:
- (普通解法):
没想出一趟遍历的,普通做法,先把链表遍历一遍,得出链表的长度,然后再由n便可遍历到需要删除的倒数第n个结点的前驱结点,然后将其指向第n个结点的后继即可实现删除。
这样是存在缺陷的,因为如果链表长度与n值相同,即要删除头结点的时候,如果长度小于2就会直接使头结点指向NULL,又或者指向第三个结点从而结果错误。所以当相等时直接使头结点指向第二结点就好了。
另外,还需判断空链表的情形,此时返回NULL。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int num=0;
ListNode *p=head;
if(head->next==NULL)
return NULL;
while(p)
{
num++;
p=p->next;
}
//cout<<num;
p=head;
if(num!=n)
{
for(int i=0;i<num-n-1;i++)
{
p=p->next;
}
if(p->next->next)
p->next=p->next->next;
else
p->next=NULL;
}
else
{
head=head->next;
}
return head;
}
};
-
(一趟遍历)
待更。。。 -
(leetcode范例,思路和我的相似,也是两趟遍历…)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int size = 1;
ListNode* node = head; //指向头结点
ListNode* temp;
ListNode* pre;
while(node->next != NULL){
++ size;
node = node->next;
}
if(size == 1)
return head = NULL;
node = head;
for(int i = 0; i < size-n; ++ i){
if(node -> next != NULL){
pre = node;
node = node->next;
}
}
if(node -> next != NULL){
temp = node->next;
node->val = temp->val;
node->next = temp->next;
delete temp;
}else{
pre->next = NULL;
delete node;
}
return head;
}
};