此道题目,我也只是遍历一次链表,但是因为使用了vector所以,空间复杂度为O(N),我的代码如下:
ListNode* removeNthFromEnd(ListNode* head, int n) {
vector<ListNode *> pointers; // 存储指针
ListNode* tmp = head;
while (tmp != NULL) {
pointers.push_back(tmp);
tmp = tmp->next;
}
if (pointers.size()-n == 0) {
tmp = head->next;
delete head;
return tmp;
}
ListNode* pointer = pointers[pointers.size()-n-1];
tmp = pointer->next;
pointer->next = pointer->next->next;
delete tmp;
return head;
}
而事实上的经典解法是通过双指针,这时的空间复杂度为O(1)。我们设快慢两个指针,快指针先走n步,然后两个指针再同时向前走,当快指针走到链表的最后一个元素时,慢指针恰好走到要删除的元素的前一个元素。那么怎么理解这种解法呢,细心一思考便知,快指针先走n步后,到达链表的第n+1个元素,而快指针要到达最后一个元素的话,要再走Len-1-n步,Len为链表的长度。当慢指针向前走Len-n-1步时,到达链表的第Len-n个元素。其下一个元素为Len-n+1,恰好是从右边数第n个元素。代码如下:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (head == NULL) {
return NULL;
}
ListNode *fast = head, *slow = head, *tmp; // 快慢两个指针
for (int i=0; i<n; i++) {
fast = fast->next;
}
if (fast == NULL) {
tmp = head;
head = head->next;
delete tmp;
return head;
}
while (fast->next != NULL) {
fast = fast->next;
slow = slow->next;
}
tmp = slow->next;
slow->next = tmp->next;
return head;
}