LeetCode19. 删除链表的倒数第 N 个结点
1.题目
2.思路
1.我自己的思路很简单粗暴,就是:
(1)求出链表长度(2)通过计算把倒数换为正数(3)删除结点
注意特判头结点!!使用哨兵结点方便处理头结点!!
2.简化版——利用双指针,仅需一趟扫描
下面分别实现。
3.代码实现
(1) 倒序转正序
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int size = 0;//链表长度
ListNode* dummyHead = new ListNode(-1,head);//哨兵结点
ListNode* p = dummyHead;
while(p->next!= NULL)//第一次遍历:统计链表长度
{
p = p->next;
size++; //链表长度
}
int a = size-n+1;//待删除的结点正序所在位置 从1开始!!
if(a == 1)//特判头结点
{
ListNode*q = head;
dummyHead->next = head->next;
head = head->next;//连接节点
delete q;
delete dummyHead;
return head;
}
else//其他情况
{
ListNode *q = dummyHead;
//从哨兵结点出发 只需要走 待删除结点的所在正序-1 步即可
int cnt = size-n;
while(cnt--)//第二次遍历
q = q->next;
ListNode *m = q->next;
q->next = m->next;//连接节点
delete m;
delete dummyHead;
return head;
}
}
};
注意事项
1.注意题目条件:n一定在size范围内
2.一个小总结,感觉自己每次在这里都会思考一下,有点浪费时间:
统计链表长度,如果从哨头结点出发要用
while(p->next!= NULL)
从头结点出发则是
while(p != NULL)
(2) 双指针
最重要的就是省去了求链表长度的步骤!!也不需要特判头结点!!
实现点:1.哨兵结点 2.双指针
思路见注释:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(-1,head) ;
ListNode* fast = dummyHead;//快指针
ListNode* slow = dummyHead;//慢指针
int a = n+1;
//1.快指针先走n+1步——为了使后期同步动时slow指向待删除结点的前一个,方便操作
while(a--)
fast = fast->next;//向后移n+1步
//2.快慢指针同步动,
while(fast!=NULL)
{
slow = slow->next;
fast = fast->next;
} //此时slow指向待删除结点的前一个结点
//3.删除操作
ListNode*p = slow->next;
slow->next = p->next;
delete p;
return dummyHead->next; //注意这里!
}
};
1.特别要注意的是最后一句
return dummyHead->next;
因为原来的头结点head可能已经被删去,新的头结点就是dummyHead->next。
2.n的值一定合理,所以不需要考虑太多!不会有指空的情况!