leetcode删除链表中的节点(【Leetcode】移除链表元素 链表的中间节点 链表中倒数第k个节点)
目录
一.【Leetcode203】移除链表元素
1.链接
2.题目再现
A.双指针法
B.类尾删法
C.哨兵位
二.【Leetcode876】链表的中间节点
1.链接:链表的中间节点
2.题目再现
3.解法:快慢指针
三.链表中倒数第k个节点
1.链接:链表中倒数第k个节点
2.题目再现
3.解法 :快慢指针
一.【Leetcode203】移除链表元素
1.链接
移除链表元素
2.题目再现
A.双指针法
1.创建一个指针 cur=head 和一个指针 pre=NULL;
2.用cur->val 与 val 比较,如果不相等则把 cur 赋给 pre 使cur 指向下一个节点 ,即
cur=cur->next;
3.如果相等则使 pre 的 next 指向 cur 的 next ,即:
pre->next=cur->next ,然后再 free 掉 cur ,最后再使 cur 等于 pre 的 next ,注意在进行这些步骤之前要判断 pre 是否为空 ,若为空即为头删;
演示:
代码:
struct ListNode* removeElements(struct ListNode* head, int val) { struct ListNode*pre=NULL; struct ListNode*cur=head; while(cur) { if(cur->val!=val) { pre=cur; cur=cur->next; } else { if(pre==NULL) { head=cur->next; free(cur); cur=head; } else { pre->next=cur->next; cur=pre->next; } } } return head; }B.类尾删法
1.创建一个新的指针newhead ,同时为了省去找尾的麻烦 ,我们可以定义一个尾指针 tail 来保存尾节点;
2.再创建一个指针 cur =head ,用来遍历链表;
3.如果 cur->val != val ,则尾插 ,注意要判断 tail 是否为空 ,类似于单链表的尾插那部分 ,如果不理解的话 ,可查看文章 :单链表的增删查改;
4.如果 cur->val ==val,则 cur=cur->next ;
5.最后要将尾节点置空 。
演示:
类尾插
代码:
struct ListNode* removeElements(struct ListNode* head, int val) { struct ListNode *newhead=NULL; struct ListNode*tail=NULL; struct ListNode*cur=head; while(cur) { if(cur->val!=val) { if(tail==NULL) { newhead=tail=cur; } else { tail->next=cur; tail=tail->next; } cur=cur->next; } else { cur=cur->next; } } if(tail) { tail->next=NULL; } return newhead; }C.哨兵位
1.malloc 一个哨兵位节点 dummyhead ,使其 next 指向 head ;
2.再定义一个节点 tmp = dummyhead ,用这个遍历链表;
3.注意因为 tmp ->next 才是 head ,所以 while 里要写 tmp->next !=NULL
演示:
移除链表元素 哨兵位法动态演示
代码:
struct ListNode* removeElements(struct ListNode* head, int val) { struct ListNode*dummyhead=(struct ListNode*)malloc(sizeof(struct ListNode)); dummyhead->next=head; struct ListNode*tmp=dummyhead; while(tmp->next!=NULL) { if(tmp->next->val==val) { tmp->next=tmp->next->next; } else { tmp=tmp->next; } } return dummyhead->next; }二.【Leetcode876】链表的中间节点
1.链接:链表的中间节点
2.题目再现
3.解法:快慢指针
1.定义一个快指针 fast 和一个慢指针 slow 都初始化为 head;
2.遍历链表 ,快指针一次走2步 ,慢指针一次走1步 ;
3.注意:因为链表的长度可能是单数也可能是双数 ,所以当我们已 fast 是否为NULL 作为循环控制条件的话 ,要在 fast 走2步前判断 fast->next 是否为空;
4.最后慢指针就是中间节点 。
演示:
链表中间节点 快慢指针动态演示
代码:
struct ListNode* middleNode(struct ListNode* head) { struct ListNode*slow=head; struct ListNode*fast=head; while(fast) { if(fast->next==NULL) //注意判断 { break; } else { fast=fast->next->next; //fast 走2步 } slow=slow->next; //slow 走1步 } return slow; //返回慢指针 }三.链表中倒数第k个节点
1.链接:链表中倒数第k个节点
2.题目再现
3.解法 :快慢指针
1.定义一个快指针 fast 和一个慢指针 slow 都初始化为 head;
2.因为倒数第k个节点和尾节点的差为 k-1 ,所以我们先让快指针先走 k-1 步;
或者因为尾节点所指向的NULL 和倒数第k个节点相差k ,也可以先让快指针走k步;
这个时候慢指针不动;
3.快指针走完后 ,快指针和慢指针依次走 ,每次只走1步;
注意 ,如果是k-1 ,那么遍历结束的条件是fast->next 是否为空 ,如果是k ,那么遍历结束的条件是fast 是否为空;
4.返回慢指针 。
演示:
链表倒数第K个节点 快慢指针动态演示
代码:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) { if(pListHead==NULL) { return NULL; } struct ListNode*slow=pListHead; struct ListNode*fast=pListHead; while(k--) //这里以先走k步为例 { if(fast==NULL) { return NULL; } fast=fast->next; } while(fast) { slow=slow->next; fast=fast->next; } return slow; }😽本篇文章到此就结束了,若有错误或是建议 ,欢迎小伙伴们指出;😻
😍请多多支持博主哦~🥰
🤩谢谢你的阅读~😃
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!