• leetcode刷题——单链表


    目录

    练习题1移除链表元素

    带哨兵头

    练习题2合并两个有序链表  ​编辑

    练习题3反转链表 

    习题4 链表的中间节点 

    习题5 倒数第K个节点 

    练习题1移除链表元素

    点这里跳转做题

     要考虑的情况

     

    如果只有一个节点,且这个节点要删除,则返回NULL 

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. while(head != NULL && head->val == val){
    3. head = head->next;
    4. }
    5. struct ListNode* fast = head;
    6. struct ListNode* slow =head;
    7. struct ListNode* slow1 =head;
    8. if (head ==NULL)
    9. return NULL;//如果头节点为空,则直接返回
    10. while (fast!= NULL)
    11. {
    12. while (fast->val!=val)
    13. {
    14. slow = fast;
    15. if (slow->next == NULL)
    16. return head;//如果遍历完整个链表,fast为NULL,都没找到val,则直接返回
    17. fast = fast->next;
    18. }
    19. if (fast->val == val)
    20. {
    21. slow->next = fast->next;
    22. fast = fast->next;//跨过要删除的节点
    23. }
    24. }
    25. if (slow1->val==val)//如果只有一个节点,且这个节点要删除,则返回空
    26. return NULL;
    27. return head;
    28. }

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode* cur=head;
    3. struct ListNode* prve=NULL;
    4. while(cur)
    5. {
    6. if(cur->val==val)
    7. {
    8. if(cur==head)
    9. {
    10. head=head->next;
    11. free(cur);
    12. cur=head;
    13. }
    14. else
    15. {
    16. prve->next=cur->next;
    17. free(cur);
    18. cur=prve->next;
    19. }
    20. }
    21. else
    22. { prve=cur;
    23. cur=cur->next;
    24. }
    25. }
    26. return head;
    27. }

    还可以把 非valu的节点,插到新链表

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode* cur=head;
    3. struct ListNode* tail=NULL;
    4. struct ListNode* newhead=NULL;
    5. while(cur)
    6. {
    7. if(cur->val!=val)
    8. {
    9. if(tail==NULL)
    10. {
    11. tail=newhead=cur;
    12. }
    13. else
    14. {
    15. tail->next=cur;
    16. tail=tail->next;
    17. }
    18. cur=cur->next;
    19. }
    20. else
    21. {
    22. struct ListNode* del=cur;
    23. cur=cur->next;
    24. free(del);
    25. }
    26. }
    27. if(tail)
    28. tail->next=NULL;
    29. return newhead;
    30. }

    带哨兵头

     

    head不存储有效数据

    1. struct ListNode* removeElements(struct ListNode* head, int val){
    2. struct ListNode* guard=(struct ListNode* )malloc(sizeof(struct ListNode));
    3. struct ListNode*tail=guard;
    4. struct ListNode*cur=head;
    5. while(cur)
    6. {
    7. if(cur->val!=val)
    8. {
    9. tail->next=cur;
    10. tail=tail->next;
    11. cur=cur->next;
    12. }
    13. else
    14. {
    15. struct ListNode* del=cur;
    16. cur=cur->next;
    17. free(del);
    18. }
    19. }
    20. if(tail)
    21. tail->next=NULL;
    22. return guard->next;
    23. }

    带哨兵位的头节点,传参的时候不需要传二级指针

    替代之前的二级指针:

    1.返回新链表头

    2.设计为带哨兵位

    单链表:

    1.实际运用中很少带头

    2.OJ题基本不带头

    练习题2合并两个有序链表  

    1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    2. struct ListNode*newhead=(struct ListNode*)malloc(sizeof(struct ListNode));
    3. struct ListNode*tail=newhead;
    4. while(list1!=NULL&&list2!=NULL)
    5. {
    6. if(list1->val>list2->val)
    7. {
    8. newhead->next=list2;//newhead与第小的数链接
    9. list2=list2->next;//遍历下一个数
    10. }
    11. else
    12. {
    13. newhead->next=list1;
    14. list1=list1->next;
    15. }
    16. newhead=newhead->next;//newhead往下走,要存下一个数
    17. }
    18. while(list1!=NULL)
    19. {
    20. newhead->next=list1;
    21. list1=list1->next;
    22. newhead=newhead->next;
    23. }
    24. while(list2!=NULL)
    25. {
    26. newhead->next=list2;
    27. list2=list2->next;
    28. newhead=newhead->next;
    29. }
    30. newhead->next=NULL;
    31. return tail->next;
    32. }

    练习题3反转链表 

    点这里跳转

    1. struct ListNode* reverseList(struct ListNode* head){
    2. struct ListNode*cur=head;
    3. struct ListNode*next=NULL;
    4. struct ListNode*newhead=NULL;
    5. while(cur)
    6. {
    7. next=cur->next;
    8. cur->next=newhead;
    9. newhead=cur;
    10. cur=next;
    11. }
    12. return newhead;
    13. }

     方法二:反转链表

    1. struct ListNode* reverseList(struct ListNode* head){
    2. struct ListNode*cur=head;
    3. struct ListNode*prve=NULL;
    4. while(cur)
    5. {
    6. struct ListNode*t=cur->next;
    7. cur->next=prve;
    8. prve=cur;
    9. cur=t;
    10. }
    11. return prve;
    12. }

    习题4 链表的中间节点 

    点这里跳转

    1. struct ListNode* middleNode(struct ListNode* head){
    2. struct ListNode*fast,* slow;
    3. fast=slow=head;
    4. while(fast&&fast->next)
    5. {
    6. slow=slow->next;
    7. fast=fast->next->next;
    8. }
    9. return slow;
    10. }

     采用快慢指针:快指针一次走俩步,慢指针走一步

    习题5 倒数第K个节点 

    采用快慢指针法

    方法一:fast先走k步,然后slow和fast一块一步一步走,等fast位空,则停止前进,slow所在位置就是倒数第k个

    这里k=4,则slow要等于倒数第四个

     

    fast为空,找到了

    方法二:fast先走k-1补,然后slow和fast一起一步一步走,等fast->next=NULL,则找到了 

    1. struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    2. struct ListNode* fast=pListHead;
    3. struct ListNode *slow=pListHead;
    4. if(pListHead==NULL)
    5. return NULL;
    6. while(k--)
    7. {
    8. if(fast)
    9. fast=fast->next;
    10. else
    11. return NULL;
    12. }
    13. while(fast)
    14. {
    15. slow=slow->next;
    16. fast=fast->next;
    17. }
    18. return slow;
    19. }

  • 相关阅读:
    第二章第十二节:set集合
    EasyExcel的使用
    DataOps不是工具,而是帮助企业实现数据价值的最佳实践
    failed to create symbolic link ‘/usr/bin/mysql’: File exists
    Java - postman访问登录接口失败 (cookie会话不一致)
    【RuoYi-Vue-Plus】登陆逻辑的实现
    ABAP接口部分-Web Service提供者与消费者
    VBox启动失败、Genymotion启动失败、Vagrant迁移
    白嫖GitHub Action实现开源项目CICD
    SpringBoot限制接口访问频率 - 这些错误千万不能犯
  • 原文地址:https://blog.csdn.net/weixin_49449676/article/details/126086696