环形链表的约瑟夫问题

本文介绍了环形链表版本的约瑟夫问题,通过构建不带头的单向循环链表并实现逢m删除节点的逻辑,演示了解决此经典算法问题的方法。作者分享了代码示例,并给出了最终幸存者编号的计算过程。
摘要由CSDN通过智能技术生成

前言

大家好呀,我是Humble,今天要分享的内容是环形链表的约瑟夫问题

说到链表,约瑟夫问题(约瑟夫环)绝对是一个经典的算法题,下面就让我们一起看一下吧~

正文开始前,我们先看一个小小的故事,借此引出主题,如果能勾起大家学习的兴趣就太好啦~


据说历史上有过这样的故事:在罗马人占领乔塔帕特后,39个犹太人与约瑟夫及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式:

41个人排成⼀圈,由第1个人开始报数,每报数到第3人,该人就必须自杀,然后再由下一个人重新报数,直到所有人都自杀身亡为止


然而约瑟夫和他的朋友并不想遵从。约瑟夫要他的朋友先假装遵从,他将朋友与自己安排在
第16个与第31个位置,于是逃过了这场死亡游戏


好,看完这个故事,不知道你有什么感想?下面我们回归正题,来做一下有这段轶事衍生出的约瑟夫问题吧~


正文

环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)

题目描述:

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开

下一个人继续从 1 开始报数。

n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?

对于这道题目,Humble的思路是:
1.根据n来创建不带头的单向循环链表

2.逢m删除当前节点

实现的代码如下:

//为了方便,我们另外封装了两个函数,
//一个用来申请新的节点,一个用来创建不带头单向循环链表~

typedef struct ListNode ListNode;//偷个懒,将struct ListNode重命名为ListNode,嘿嘿

ListNode* BuyNode(int x)
{
   ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));

   newNode->val = x;
   newNode ->next = NULL;
   
   return newNode;
}

ListNode* createlist(int n)
{
    ListNode* phead = BuyNode(1);
    ListNode* ptail = phead;
    for (int i =2;i<=n;i++)
    {
        ptail->next = BuyNode(i);
        ptail = ptail->next;
    }
     ptail->next = phead;//让链表构成环

     return ptail;//返回尾节点

}

int ysf(int n, int m )
 {
   ListNode* prev = createlist(n);//前驱,因为链表是循环的所以初始放在尾节点
   ListNode * head = prev->next;
   ListNode* pcur  = head;

   int count = 1;//计数;

   while (pcur->next != pcur)
   {
       if(count == m)
       {
        prev->next = pcur->next;
        free(pcur);
        pcur =  prev->next;
        count = 1;
       }
        
        else 
        {
          prev  = pcur;
          pcur = pcur->next;
          count++;
        }

   }

//循环结束后,此时的pcur节点就是幸存下来的唯一的节点了
return pcur->val; //输出幸存者的编号
  
}

运行结果如下:

结语

好了,今天关于约瑟夫环的分享就到这里了,如果对大家有帮助就太好啦~

在学习编程的道路上Humble与各位同行,加油吧各位!

最后希望大家点个免费的赞或者关注吧(感谢感谢),也欢迎大家订阅我的专栏

让我们在接下来的时间里一起成长,一起进步吧!

e0d3d2143b284925a6e6d82b6cd73662.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不吃肉的Humble

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

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

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

打赏作者

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

抵扣说明:

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

余额充值