题目来源于力扣–https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xn2925/
一、最容易想到的方法就是,计算出链表的长度,用长度减去n就是要删除节点的前一个节点,这里要注意的是,如果计算出来的节点位置为0,表示要删除第一个节点,直接头指针往后移一下就可以了。知道了前一个节点,删除后边的节点就好办了。假设指针p指向前驱结点,用一个临时的指针q指向要删除的节点,p->next = q->next,free(q),q=NULL,就把q指向的节点删除了
看图:
main函数代码
#include<stdio.h>
#include<stdlib.h>
struct ListNode* removeNthFromEnd(struct ListNode* head, int n);
// 结构体
struct ListNode {
int val;
struct ListNode *next;
};
int main(){
// 动态申请四个空间
struct ListNode *a = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *b = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *c = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *d = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *e = (struct ListNode *)malloc(sizeof(struct ListNode));
// 赋值
a->val = 1;
b->val = 2;
c->val = 3;
d->val = 4;
e->val = 5;
// 指针连接
a->next = b;
b->next = c;
c->next = d;
d->next = e;
e->next = NULL;
// 调用函数
struct ListNode *head = removeNthFromEnd(a,2);
// 遍历链表
while(head!=NULL){
printf("%d",head->val);
head = head->next;
}
return 0;
}
删除节点代码
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
// 指针p指向头结点
struct ListNode *p = head;
int count = 1;
// 计算节点数量
while(p->next!=NULL){
count++;
p=p->next;
}
// 要删除节点的前一个节点位置
int prePos = count-n;
// 表示删除第一个节点
if(prePos==0){
// 头指针后移
head = head->next;
return head;
}
// p指向头节点
p = head;
// p指向前一个节点
for(int i=1;i<prePos;i++){
p = p->next;
}
// 临时指针q指向删除节点
struct ListNode *q = p->next;
// p的next指向q指向节点的下一个节点
p->next = q->next;
// 释放q所指的节点空间
free(q);
// 置空,防止野指针
q = NULL;
return head;
}
二、还有一种方法是双指针法,两个指针同时指向头结点,一个指针为p,一个指针为q,p先往前走n次,然后就判断p->next为不为空,如果p是NULL的话,表示删除的是头结点。否则的话,继续判断p->next,只要不为NULL,p往后走,q也往后走。直到p->next为NULL,此时q所指的就是要删除节点的前驱节点。这么神奇的吗?
main函数代码与前边一致
删除节点代码
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
// 指针p,q指向头结点
struct ListNode *p = head;
struct ListNode *q= head;
// 向前走n次
for(int i=0;i<n;i++){
p = p->next;
}
// 如果为空,则是删除头结点
if(p==NULL){
head = head->next;
return head;
}
// 寻找被删除节点的前一个节点
while(p->next){
p = p->next;
q = q->next;
}
// 临时指针temp指向删除节点
struct ListNode *temp = q->next;
// q的next指向temp指向节点的下一个节点
q->next = temp->next;
// 释放temp所指的节点空间
free(temp);
// 置空,防止野指针
temp = NULL;
return head;
}