题目:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
思路:
-
方法一: 使用vector记录每一个位置元素的指针
遍历一次后,从vector中直接找到这个元素进行删除; -
方法二:使用双指针:
初始化两个指针的位置相间为 N个元素,当前面的元素到达终点,前面的元素自然就是倒数第N个元素;
代码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) {
vector<ListNode*> pvec;
ListNode* p = head;
while(p)
{
pvec.push_back(p);
p = p->next;
}
ListNode* q = pvec[pvec.size() - n];
if(q == head){
head = head->next;
return head;
}
else {
q = pvec[pvec.size() - n - 1];
q->next = q->next->next;
}
return head;
}
};
方法二:
/**
* 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* pre_head = new ListNode(0);
pre_head ->next = head;
ListNode* p = pre_head , *pre = pre_head;
for(int i = 0;i < n; i++) // 先将p移动n个位置
p = p->next;
// 开始移动两个指针;停下时,pre指向欲删除的前一个元素;
while(p->next)
{
p = p->next;
pre = pre->next;
}
ListNode* to_del = pre->next;
pre->next = to_del->next;
head = pre_head->next;
delete(pre_head);
delete(to_del);
return head;
}
};