环形链表的约瑟夫问题

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

通过读题,我们可以列出一个简单的例子来理解题意。比如示例1

我们从1开始报数,报到2时,那个人便离开,之后便以下一个人为开始,重新报数

最终如图所示,剩下3

通过这样举例,我们可以想到使用环形链表来解决这个问题,与一般链表不同的是,环形链表的最后一个结点的指针并不为NULL,而是重新指回第一个结点

同时,我们也需要prev指针来记录当前遍历的结点的前一个结点

代码如下

 typedef struct ListNode ListNode;
 //创建结点
 ListNode* buynode(int x)
 {
        ListNode* node = (ListNode*)malloc(sizeof(ListNode));
        node->val = x;
        node->next = NULL;
        return node;
 }
 //创建环形链表
 ListNode* CreatCircle(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 = CreatCircle(n);
    ListNode* pcur = prev->next;
    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++;
        }
    }
    //此时剩下的结点就是所求值
    return pcur->val;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值