单链表经典算法题2

                                                🌹个人主页🌹喜欢草莓熊的bear

                                                       🌹专栏🌹:数据结构


前言

这次介绍的题会比上次更有难度哦,宝宝们系好安全带。咱们出发了!

一、合并两个有序链表

 

1.1思路

创建一个新链表来接收合并后的链表(同时也会创建两指针分别为头指针和尾指针,我们这里创建的是一个带头链表),用两个指针分别来遍历两个链表。因为要升序,所以谁小就把谁为尾插到新链表里面去。我们循环结束的条件是两个遍历的指针不为空。但是必定会有一个指针先指向空指针,所以我还要在循环结束后加上一天尾插语句(因为不确定是谁先走完,所以两条都要写)。根据示列3得知,其中一个为空链表就直接返回另外一条链表。因为我们是创建了链表所以还要记得free了。

1.2代码实现

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    ListNode* l1 = list1;
    ListNode* l2 = list2;
    if(l1 == NULL)
    {
        return l2;
    }
    if(l2 == NULL)
    {
        return l1;
    }
ListNode* head,* ptail;
head=ptail=(ListNode*)malloc(sizeof(ListNode));//创建一个带头链表
while(l1 && l2)
{
    if(l1->val < l2->val)
    {
        ptail->next=l1;
        ptail=l1;
        l1=l1->next;
    }
    else
    {
        ptail->next=l2;
        ptail=l2;
        l2=l2->next;
    }
}
if(l1)
{
    ptail->next=l1;
}
if(l2)
{
    ptail->next=l2;
}
ListNode* ret=head->next;
free(head);
head=NULL;
return ret;
}

二、环形链表的约瑟夫问题

 

2.1思路

第一步节点的创建,在之前的单链表中就写过的。

其次我们要得到一个环形链表,怎么做呢?就是让链表尾节点指向头节点,定义两个指针分别头指针和尾指针。

再者我们得到了环形链表所以就要开始考虑计数了,假设我只定义一个指针,释放了计数为2的节点那么就会导致我们找不到后面的节点了。所以我们要定义两个指针prev指针指向头节点,patil指针指向尾节点。循环里面当计数为2时,我们就先改变patil->next指向prev->next指针,再把prev指向patil->next。不等于时,则计数加1和prev、patil向后移动(先移动patil,再移动prev),这里循环的条件计算prev!=环形链表的头指针。防止出现空指针,该指向空指针指向空指针,该释放的释放。释放之前把最后得到的节点的val值储存起来,然后返回val。

2.2代码实现

typedef struct ListNode ListNode;
ListNode* BuyNode(int x)//创建节点
{
    ListNode* node=(ListNode*)malloc(sizeof(ListNode));
    if(node==NULL)
    {
        exit(1);
    }
    node->val=x;
    node->next=NULL;
    return node;
}

ListNode* cyclelist(int n)//形成环形链表
{
    ListNode* head=BuyNode(1);
    ListNode* patil=head;
    for(int i=2;i<=n;i++)
    {
        patil->next=BuyNode(i);
        patil=patil->next;
    }
    patil->next=head;
    return patil;
}

int ysf(int n, int m ) 
{
    ListNode* patil=cyclelist(n);
    ListNode* prev=patil->next;
    int count=1;
    while(prev->next!=prev)
    {
        if(count==m)
        {
            patil->next=prev->next;
            free(prev);
            prev=patil->next;
            count=1;
        }
        else 
        {
            patil=prev;
            prev=prev->next;
            count++;
        }
    }
    prev->next=NULL;
    int ret=prev->val;
    free(prev);
    prev=NULL;
    return ret;
}

总结

做这种链表题一定要画图,结合图做起来比较好。好了我们的单链表经典算法题就结束了,不记得了就来bear这回顾哦。后期还会有其他题目讲解,有不同的想法也可以写道评论区,有写错的地方望指正。宝宝们晚安🌹🌹

  • 33
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值