【leetcode-19】删除链表的倒数第N个结点

using namespace std;
#include <iostream>
struct ListNode {
int val;
ListNode* next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* fast = head;
ListNode* slow = new ListNode(0, head);
cout << "fast aka head's address: "<<fast << endl;
cout << "slow next address: "<<slow->next << endl;
for (int i = 0; i < n; ++i) {
fast = fast->next;
cout <<"fast address after moving n steps: " <<fast << endl;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
if (slow->next != nullptr) {
slow->next = slow->next->next;
cout << "slow next address after delete the target node: "<<slow->next << endl;
}
cout << "head address after delete the target node: "<<head << endl;
return head;
}
};
int main()
{
ListNode head = ListNode(1);
Solution s;
s.removeNthFromEnd(&head, 1);
}
运行结果(请原谅我的塑料英语哈哈哈,正在努力养成英文注释的习惯中~):
一般在链表的问题中,使用双指针解法需要设置一个哑结点指向链表头。该解法的错误用例为示例2,当完成结点的删除后,slow->next指向新的”链表头“也即地址00000000,而原先的头结点head仍然指向原地址00FCFBFC,所以此时返回的并不是链表头。
正确解法:
using namespace std;
#include <iostream>
#include <vector>
#include <unordered_map>
#include<string>
struct ListNode {
int val;
ListNode* next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pre = new ListNode(0, head);
cout << "pre's address: " << pre << endl;
ListNode* fast = head;
cout << "fast/head's address: " << fast << endl;
ListNode* slow = pre;
cout << "slow's address: " << slow << endl;
for (int i = 0; i < n; ++i) {
fast = fast->next;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
cout << "slow next's address: " << slow->next << endl;
ListNode* res = pre->next;
cout << "pre's address: " << pre << endl;
cout << "res's address: " << res << endl;
cout << "head's address: " << head << endl;
delete pre;
return res;
}
};
int main()
{
ListNode head = ListNode(1);
Solution s;
s.removeNthFromEnd(&head, 1);
}
加入哑结点后,可以保存原先指向头结点的”结点“,也就能保证该”结点“的next始终是我们所想要的链表头。