力扣刷题笔记-删除链表的倒数第N个结点
力扣题目-删除链表的倒数第N个结点C++实现
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
分析:
这一题最重要的是怎么找到倒数第n个结点,因为链表的长度其实我们是不知道的,这里指向链表的指针只能单向移动,按一般的思路的话我们用指针只有遍历完一遍确定链表的长度之后,才能确定倒数第n个结点的位置,然后再从头开始遍历去找这个结点把它删掉。
这里可以使用一个巧妙的办法,就是使用双指针。我们可以分析一下如果链表的长度是lenth的话,用一个指针p指向第一个节点,那p移动多少次可以指向l倒数第N个结点呢?lenth-N次。看例子,lenth长度为5,指向第一个节点的p移动5-2=3次之后恰好指向4也就是倒数第二个结点。然后这里再设置一个指针q,刚开始的时候让指针q指向第一个结点,然后向右移动N,此时p和q的距离也是N。比如例子里边刚开始p指向1,那么就把q放在位置3。
然后让p和q同时往右边移动,直到q指向空的时候看看是什么状态。
这个时候q刚好是从第N个位置移到了空位置,相当于移动了lenth-N次,这时候我们发现p也就是跟着移动了lenth-N次。前面我们怎么分析的?p移动多少次可以指向l倒数第N个结点呢?lenth-N次,所以这时候恰好p指向的那个结点就是我们要删除的结点了。这个例子里,p和q都移动了3次,此时p恰好指向要删除的结点4。
另外还需要注意的是,我们还需要一个pre结点指向p前面的结点以便执行删除操作。我们删除的结点有可能是第一个结点,那么这时候pre就不好弄了,不知道怎么指,所以为了更好地操作,可以先生成一个虚拟头结点dummyHead, 作为 “临时起点”,可以直接把链表挂在后面,这样操作起来就更加方便。
pre ,p , q都向右移动,直到q指向空的时候停下来,这时候p指向了要删除的那个结点,然后pre->next=p->next,完成结点的删除,最后直接返回dummyHead->next就是删除后的链表。
class solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummyHead = new ListNode(0);dummyHead->next = head;ListNode* pre = dummyHead;ListNode* p = head;ListNode* q=head;for (int i = 0; i < n; i++) {q = q->next;//把q移动n次}while (q) {//q没指向空就一直操作q = q->next;pre = p;p = p->next;}pre->next = p->next;//删除结点return dummyHead->next;}
};