19.删除链表的倒数第N个节点
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
思路
本题思路有二:
第一种:
自己的做法。
- 使用虚拟头节点对链表进行反转操作
- 用cnt从前遍历n个,然后删除该节点
- 再次使用虚拟头节点对链表进行反转
第二种:
双指针、虚拟头节点法做。
为什么要用虚拟头节点的方法做?
因为用虚拟头节点做的话可以不用考虑删除的元素是否为头节点。虚拟头节点一直指向的是链表的头节点的位置,就算链表的头结点变了,虚拟头节点还是可以link到新的头节点的位置。
- 使用一个快指针前进n+1个节点
- 快、慢指针同时向前走,直到快指针遍历结束
- 此时慢指针指向n-1元素的位置,直接删除第n个元素即可
以下c语言的做法就是用的第一种方法做的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { typedef struct ListNode ListNode; ListNode* pre = NULL; ListNode* cur = head; ListNode* temp = NULL; while(cur){ temp = cur->next; cur->next = pre; pre = cur; cur = temp; } int cout =1; ListNode* phead = (ListNode*)malloc(sizeof(ListNode)); phead->next = pre; cur = phead; while(cur->next){ if(cout == n){ cur->next = cur->next->next; break; }else{ cout++; cur = cur->next;} } pre = NULL; cur = phead->next; while(cur){ temp = cur->next; cur->next = pre; pre = cur; cur = temp; } return pre; }
|
以下c++代码实现第二种方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* phead = new ListNode; phead->next = head; ListNode* fast = phead; ListNode* low = phead; while(n-- && fast->next){ fast = fast->next; } fast = fast->next; while(fast){ fast = fast->next; low = low->next; } ListNode* temp = low->next; low->next = low->next->next; delete temp; return phead->next; } };
|