题目:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
解答:
自己的解答:
ListNode* removeNthFromEnd(ListNode* head, int n) { if (n <= 0) return head; ListNode* tmp = head; int num = 0; while (tmp != nullptr) { num++; tmp = tmp->next; } if (n == num) return head->next; ListNode* headTmp = head; ListNode* pre; int deleteK = num - n; int idx = 0; while (idx < deleteK) { pre = headTmp; headTmp = headTmp->next; idx++; } pre->next = headTmp->next; delete headTmp; return head; }
答案里用双指针:
由于我们需要找到倒数第 n 个节点,因此我们可以使用两个指针 first 和 second 同时对链表进行遍历,并且first 比second 超前 n 个节点。当first 遍历到链表的末尾时,second 就恰好处于倒数第 n 个节点。
具体地,初始时first 和 second 均指向头节点。我们首先使用first 对链表进行遍历,遍历的次数为 n。此时,first 和 second 之间间隔了 n−1 个节点,即first 比second 超前了n 个节点。
在这之后,我们同时使用first 和 second 对链表进行遍历。当 first 遍历到链表的末尾(即 first 为空指针)时,second 恰好指向倒数第 n 个节点。
根据该思路编写代码如下:
ListNode* removeNthFromEnd2(ListNode* head, int n) { if (n == 0) return head; ListNode* tmp = head; int num = 0; while (tmp != nullptr) { num++; tmp = tmp->next; } if (n == num) return head->next; ListNode* first = head; ListNode* second = head; int idx = 0; while (idx < n) { first = first->next; idx++; } while (first->next != nullptr) { first = first->next; second = second->next; } first = second; second = second->next; first->next = second->next; delete second; return head; }
看了题解的答案,并没有统计链表元素的个数,解答的代码如下:
示意图如下图所示:
图片来源:
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/