提示:以下是本篇文章正文内容,下面案例可供参考
一、哑结点
在leetcode平台中, 单链表的头结点同时也作为链表的第一个结点使用
也就是说, 相对于王道数据结构书上和 前面几篇博客 的单链表表示方法中, 使用一个无数据域的结点作为虚拟头结点(head 结点)的这种方式, 在做力扣单链表题时, 会使用到添加哑结点dummy 的技巧. 这也就是前文说的虚拟头结点的技巧;
一句话就是, 在leetcode题解中在链表第一个结点钱添加dummy 哑结点就等同于构造了一个带有虚拟头结点的单链表
二、快慢指针
在leetcode-19题中, 使用到了快慢指针的技巧, 这道题的要求是删除倒数第N个结点
下面是题解
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0, head);
ListNode* first = head;
ListNode* second = dummy;
for (int i = 0; i < n; ++i) {
first = first->next;
}
while (first) {
first = first->next;
second = second->next;
}
second->next = second->next->next;
ListNode* ans = dummy->next;
delete dummy;
return ans;
}
当使用快慢指针时, 由于添加了哑结点, 因此慢指针自然而然地指向了哑结点(也就是链表第一个结点的前一个位置), 这样快慢指针就自然地区分开了. 而且当链表的结点只有一个时, 也不用判断快慢指针是否指在同一个结点上;
对于这道题, 使用快慢指针, 让fast 指针先出发n位, 与slow 拉开n位的差距, 这样当fast 指空时, slow 刚好位于需要删除的结点的前一个位置,这样接下来只要执行删除操作即可;
三、交换/删除结点
在单链表中, 交换和删除结点都是常考的操作
p->next = p->next->next;
或
q = p->next;
p->next = q->next;
p->next = node_2;
node_1->next = node_2->next;
node_2->next = node_1;
在第2步中, node1必须先和node2的后继连接上,防止后继丢失
未完待续… …
|