题目描述:
解法:
1.两次遍历算法
思路:第一次遍历链表得到链表的长度,第二次到对应位置便执行删除结点操作。
代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pre = new ListNode(-1); //添加一个哑节点
pre->next = head; //让哑节点指向链表的头节点
ListNode* first = pre; //让first指向哑节点
int length = 0;
while(first != nullptr) { //第一次遍历链表, 得出长度
first = first->next;
length++;
}
length -= n; //第二次遍历执行次数
first = pre;
while (length > 0) { //first指向第 length - n 个结点(即要删除的节点)
first = first->next;
length--;
}
first->next = first->next->next; //执行删除操作
return pre->next;
}
};
2.一次遍历算法
思路:这种算法需要两个指针,并且先执行一个循环让两个指针先相隔n个节点的距离,再遍历一次链表即可让指针指向对应节点,再删除节点。
代码:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pre = new ListNode(-1);
if (head == nullptr) {
return head;
}
pre->next = head;
ListNode* first = pre;
ListNode* second = pre;
while(n >= 0) {
second = second->next;
n--;
}
while (second != nullptr) {
first = first->next;
second = second->next;
}
first->next = first->next->next;
return pre->next;
}
注意:
哑节点的使用:在执行删除、插入等操作时,哑节点可以有效避免结点为空的边界问题,减少代码执行异常(出错)的可能性。