Leetcode 19 删除链表的倒数第N个结点
题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
题解1(暴力)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* c_head = head;
ListNode* cc_head = head;
int len = 0;
// 计算长度
while(c_head){
len++;
c_head = c_head->next;
}
int i = 1;
//找倒数第n个位置
while(i < len - n){
cc_head = cc_head->next;
i++;
}
//需要考虑处理sz=1的情况
if( i==1 && len-1 == n ||i!=1 && cc_head->next)
cc_head->next = cc_head->next->next;
else if(i == 1 && len == n)
head = head->next;
return head;
}
};
题解2(首选 快慢指针)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 链表头,创建之后无论原链表如何只需要返回dummthead->next即可
ListNode* dummyHead = new ListNode(0, head);
ListNode* p = dummyHead;
ListNode* q = dummyHead;
//令 q和头结点差出n+1来
for( int i = 0 ; i < n+1 ; i ++ ){
q = q->next;
}
//p、q同时向前,二者间距永远是n,直到q到null
//此时p正好是倒数第n+1个点
while(q){
p = p->next;
q = q->next;
}
//不考虑释放内存 : p->next = p->next->next
ListNode* delNode = p->next;
p->next = delNode->next;
delete delNode;
ListNode* retNode = dummyHead->next;
delete dummyHead;
return retNode;
}
};
------------------------------or----------------------------------------------------
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(!head->next) return head->next;
ListNode* p = head;
ListNode* q = head;
while(n--){
p = p->next;
}
//说明n=len, 所以是删除头结点,返回head->next即可
if(!p) return head->next;
// 遍历到尾结点
while(p->next){
p = p->next;
q = q->next;
}
// 慢指针到要删除的点的前一个点
q->next = q->next->next;
// 返回头节点
return head;
}
};
题解3(栈思想)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0, head);
ListNode* temp = dummyHead;
stack<ListNode*> cur;
while(temp){
cur.push(temp);
temp = temp->next;
}
//弹出n个 top是倒数第n+1个结点
for(int i = 0; i < n; i++){
cur.pop();
}
cur.top()->next = cur.top()->next->next;
ListNode* retNode = dummyHead->next;
delete dummyHead;
return retNode;
}
};
题解4(普通递归逆序处理链表:结点数少时可考虑)
class Solution {
private:
int num{0}, len{0}, t{0};
void backtrack(ListNode* l){
if(!l->next){
return;
}else{
//只要保证len、t在走完链表时相等即可
//一定是从链表尾部开始返回
len++;
t++;
backtrack(l->next);
t--;
if(len-t == num)
l->next = l->next->next;
}
}
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
num = n;
backtrack(head);
//sz==1的情况,返回nullptr
if(len+1 == n)
return head->next;
else return head;
}
};