单链表经典例题

移除链表元素

题目描述:
在这里插入图片描述
➡️挑战链接⬅️、
分析:
该题是要求我们删除指定元素,那么我们就定义一个cur指针去遍历整个链表就好了,每当我们遇到cur->val==val;等于特定值的时候我们就释放掉该节点就可以了;
如果我们遇到的不是特定值,则直接将该节点摘下来,即可;
当然,既然摘下来了,就不能让这些节点,孤单着,我门内就得找一个“线”捡起链接起来;
最后返回新头就行了;
这里我们采取不带哨兵位的方法讲解一下:
在这里插入图片描述
代码实现:

struct ListNode* removeElements(struct ListNode* head, int val){
         struct ListNode*Newhead=NULL;
         struct ListNode*tail=NULL;
         struct ListNode*cur=head;
         struct ListNode*next=NULL;
         while(cur)
         {
             if(cur->val==val)
             {
                 next=cur->next;
                 free(cur);
                 cur=next;
             }
             else 
             {
                 if(tail==NULL)
                 {
                     next=cur->next;
                     Newhead=tail=cur;
                     tail->next=NULL;
                     cur=next;
                 }
                 else
                 {
                     next=cur->next;
                     tail->next=cur;
                     tail=cur;
                     tail->next=NULL;
                     cur=next;
                 }
             }
         }
         return Newhead;
}

在这里插入图片描述
时间复杂度:O(N)
空间复杂度:O(1)

如果采用带哨兵位的头节点的话,我们就不用考虑特殊情况,直接就能在tail尾部插入,代码自然也会简短一点;
代码实现:

struct ListNode* removeElements(struct ListNode* head, int val){
           struct ListNode*dummyhead=(struct ListNode*)malloc(sizeof(struct ListNode));
           struct ListNode*prev=dummyhead;
           dummyhead->next=head;
           struct ListNode*cur=head;
           while(cur)
           {
               if(cur->val!=val)
               {
                   prev=cur;
                   cur=cur->next;
               }
               else 
               {
                   struct ListNode*next=cur->next;
                   prev->next=next;
                   cur=next;
               }
           }
           struct ListNode*newHead=dummyhead->next;
           free(dummyhead);
           return newHead;
}

在这里插入图片描述

反转链表

题目描述:
在这里插入图片描述
➡️挑战链接⬅️
分析:
反转链表,我们可以遍历一遍单链表,然后将每个单链表利用尾插的方式实现,就能达到链表反转的结果了:
在这里插入图片描述
代码实现:

struct ListNode* reverseList(struct ListNode* head){
         struct ListNode*retHead=NULL;
         struct ListNode*cur=head;
         struct ListNode*next=NULL;
         while(cur)
         {
             next=cur->next;
             cur->next=retHead;
             retHead=cur;
             cur=next;
         }
         return retHead;
}

时间复杂度:O(N)
空间复杂度:O(1)

在这里插入图片描述

合并两个有序链表

题目描述:
在这里插入图片描述
➡️挑战链接⬅️
分析:
题目给了一个很好的条件,链表有序,那么我们就可以根据归并排序的思想,对于链表进行合并;
我们同时对于连个链表进行遍历,没遇到val值,比较小的节点,我们就把它采摘下来;同时完成对于采摘下来的节点进行重新链接;
我们采取不带哨兵位实现,带哨兵位读者可以自行研究一下😊😊😊)
在这里插入图片描述
代码实现:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){    
            struct ListNode*Newhead=NULL;
            struct ListNode*tail=NULL;
            struct ListNode*l1=list1;
            struct ListNode*l2=list2;
            struct ListNode*next=NULL;
            while(l1&&l2)
            {
               if(l1->val>l2->val)
               {
                 next=l2->next;
                   if(tail==NULL)
                   {
                   Newhead=tail=l2;
                   }
                   else 
                   {
                       tail->next=l2;
                       tail=l2;
                   }
                   tail->next=NULL;
                       l2=next;
               }
               else
               {
                 next=l1->next;
                   if(tail==NULL)
                   {
                   Newhead=tail=l1;
                   }
                   else 
                   {
                       tail->next=l1;
                       tail=l1;
                   }
                   tail->next=NULL;
                       l1=next;
               }
            }
            if(l1)
              {
                  if(tail==NULL)
                  Newhead=l1;
                  else
                  tail->next=l1;
              }
            if(l2)
            {
                  if(tail==NULL)
                  Newhead=l2;
                  else
                  tail->next=l2;
              }
            return Newhead;
}

在这里插入图片描述
其实一道题需不需要带哨兵位来解决,主要还是看头节点有没有可能会被改变,如果有可能,我们就需要添加哨兵位的头节点来帮忙,这样我们就可以避免讨论很多的特殊情况;反之,我们就没比要构造哨兵位的头节点;

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南猿北者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值