1 题目描述
Given a linked list, remove the
nth node from the end of list and return its head.Note:
Given
n will always be valid.Try to do this in one pass.
难度:Medium
2 题目样例
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
3 题意分析
删除链表倒数第n个节点,同时提示了可以一次遍历完成。
4 思路分析
1 两次遍历
很容易想到的思路,第一次遍历得到长度,第二次遍历删除节点。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int len = 0;
ListNode* ptr=head;
ListNode tohead(0);
tohead.next = head;
while(ptr){
len++;
ptr = ptr->next;
}
ptr = &tohead;
while(ptr&&len!=n){
len--;
ptr = ptr->next;
}
ptr->next = ptr->next->next;
return tohead.next;
}
};
整体时间复杂度 ,空间复杂度
2 一次遍历
一次遍历需要两个指针ptr1和ptr2。
首先我们让ptr1指向head,ptr2指向使得区间[ptr1…ptr2]长度为n的节点,然后对区间整体向后移动,当ptr2指向尾节点的时候ptr1就指向了要删除的节点。
不过这里为了方便删除,可以让区间长度为n+1,同时ptr1从指向头节点的节点开始。
代码如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode tohead(0);
ListNode* first = &tohead;
ListNode* second = head;
tohead.next = head;
for(int i=1;i<n;i++)
second=second->next;
while(second->next){
first = first->next;
second = second->next;
}
first->next = first->next->next;
return tohead.next;
}
};
整体时间复杂度依旧是 ,空间复杂度 。
5 后记
个人觉得这个优化并不是很必要,但是两个指针的思想值得学习。