题目:
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1 输出:[]
示例 3:
输入:head = [1,2], n = 1 输出:[1]
思路1:暴力遍历
很简单的遍历完链表,一边遍历一边计数n,删除倒数第N个结点,即删除正数第n-N+1个结点。
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int getlen(struct ListNode* head){
int lenth=0;
while(head){
head=head->next;
lenth++;
}
return lenth;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* dummy=malloc(sizeof(struct ListNode));
dummy->val=0;
dummy->next=head;
struct ListNode* cur=dummy;
int len=getlen(head);
for(int i=0;i<len-n;i++){
cur=cur->next;
}
cur->next=cur->next->next;
struct ListNode* ans=dummy->next;
free(dummy);
return ans;
}
思路2:递归
链表天生自带的递归性质在这个简单条件面前自然也可以使用,在无法知道链表结点数的情况下,我们就自然无法在递的上面做文章,自然而然就只能在归的过程中进行计数,归一次就计数N++
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
static int N;//这里比较特别的一点就是我们使用静态变量,作用是在不同的归的栈中使得变量不改变
while(!head){
N=0;
return head;
}
head->next=removeNthFromEnd(head->next, n);
N++;
if(N==n){
struct ListNode* tmp=head->next;
free(head);
return tmp;
}
return head;
}
思路3:双指针
第一个暴力遍历的效率不高的一大原因就是因为遍历的次数重复了一次,增添一个指针自然可以渐少一次遍历,利用前后指针的范围差,准确的确定倒数第N个结点的所在处
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* dummy=malloc(sizeof(struct ListNode));
dummy->val=0;
dummy->next=head;
struct ListNode* pre=dummy;
struct ListNode* cur=dummy;
for(int i=0;i<n-1;i++){
cur=cur->next;
}
while(cur->next->next){
pre=pre->next;
cur=cur->next;
}
pre->next=pre->next->next;
struct ListNode* tmp=dummy->next;
free(dummy);
return tmp;
}
思路4:栈
用栈来装下所有的结点,再一步一步出栈。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct STACK{
struct ListNode* val;
struct STACK* next;
};
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* dummy=malloc(sizeof(struct ListNode));
dummy->val=0;
dummy->next=head;
struct STACK* stk=NULL;
struct ListNode* cur=dummy;
while(cur){
struct STACK* tmp=malloc(sizeof(struct STACK));
tmp->val=cur;
tmp->next=stk;
stk=tmp;
cur=cur->next;
}
for(int i=0;i<n;i++){
struct STACK* tmp=stk->next;
free(stk);
stk=tmp;
}
struct ListNode* pre=stk->val;
pre->next=pre->next->next;
struct ListNode* ans=dummy->next;
free(dummy);
return ans;
}