删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
方法一:
希望是O(N)的算法,通过一次遍历来解决问题.
首先题目中说了,要删除的是倒数第N个节点,那我就可以想成,他希望删除的是正数第count-N+1个节点,
接着通过在对链表进行遍历的时候计数就可以解决该问题,我们已经知道希望删除的是正数的第count-N+1个节点
那我们在遍历到正数的第count-N个节点时,停下来,就可以将第count-N+1个节点删除,并修复链表的节点关系
只是需要对删除正数的第一个节点做一下特殊的处理即可。
代码实现:
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int count=0;
struct ListNode * head_ptr=head;
while(head_ptr !=NULL){
//先通过一次遍历得到链表中有多少个节点
head_ptr=head_ptr->next;
count++;
}
int num_from_top=count-n+1; // delete node num;
//得到从正这数,应该删除的是第几个节点
head_ptr=head;
if(num_from_top == 1){
//将删除头结点的情况单独拿出来处理
struct ListNode * ptr=head_ptr;
head_ptr=head_ptr->next;
free(ptr);
goto end;
}
int num=1;
struct ListNode *cur_ptr=head; //让当前指针指向头结点
while(cur_ptr!=NULL){
// 开始循环遍历链表
if(num == num_from_top-1){ // node before the one which will be deleted;
//找到需要删除的节点的前一个节点的时候,停止遍历,此时next指针就是需要删除的节点
struct ListNode * del_node =cur_ptr->next;
cur_ptr->next=del_node->next;
free(del_node);
goto end;
}else{
cur_ptr=next_ptr;
num++;
}
}
end:
return head_ptr;
}
方法二:
使用双指针的方法,整体思路是让前面的指针先移动n
步,之后前后指针共同移动直到前面的指针到尾部为止。
首先创建了一个哨兵节点sentinel, sentinel->next指向传入的head节点,然后声明两个指针变量 start 与end
使他们都指向哨兵节点
先让start移动N下,然后接着在开始让start与end节点同时移动,当start到了结尾的NULL的时候,此时end节点刚好在需要删除的位置处
但是该题要求删除倒数第N个位置的节点,所以我们控制循环的条件,让start移动到最后一个节点即可,在例子中也就是5的位置,此时end节点应该在
3的位置,恰好就是需要删除的那个节点之前的位置,操作指针,删除节点,修复链表即可
最后将sentinel-next指向的节点返回即可。
以下的代码中,给大家了一个main函数,便于测试与调试用。
代码如下:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode * sentinel = malloc(sizeof(struct ListNode));
sentinel->next=head;
struct ListNode *ret_head=NULL;
struct ListNode * start , *end;
start=end=sentinel;
while(n!=0){
start=start->next;
n--;
}
while(start->next!=NULL){
start=start->next;
end=end->next;
}
struct ListNode *del_node=end->next;
end->next=end->next->next;
free(del_node);
ret_head=sentinel->next;
free(sentinel);
return ret_head;
}
int main(){
int nums[]={1,2,3,4,5};
int n=2;
struct ListNode * head=NULL;
struct ListNode * tail=NULL;
int nums_num=sizeof(nums)/sizeof(int);
int ii=0;
for(;ii<nums_num;ii++){
struct ListNode * ptr=malloc(sizeof(struct ListNode));
ptr->next=NULL;
ptr->val=nums[ii];
if(!head){
tail=head=ptr;
}else{
tail->next=ptr;
tail=ptr;
}
}
struct ListNode * ret_list=removeNthFromEnd(head, n);
while(ret_list !=NULL){
printf("%d->", ret_list->val);
struct ListNode * ptr=ret_list;
ret_list=ret_list->next;
free(ptr);
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。