数据结构——约瑟夫问题

  链接:环形链表的约瑟夫问题__牛客网
来源:牛客网

据说著名犹太历史学家 Josephus 有过以下故事:在罗马人占领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一种自杀方式,41 个人排成一个圆圈,由第 1 个人开始报数,报数到 3 的人就自杀,然后再由下一个人重新报 1,报数到 3 的人再自杀,这样依次下去,直到剩下最后一个人时,那个人可以自由选择自己的命运。这就是著名的约瑟夫问题。现在请用单向环形链表得出最终存活的人的编号


解析:本题重点考察链表的创建与删除,需要编码者对链表的基本性质有较为深刻的理解

如图所示每次报数杀死以个人就会涉及到一次链表的删除问题,单向链表的删除除了要找删除对象还要找对象的前一个,在这里我们用两个指针分别实现。那最初要从链表的头结点报数,前一个指针放在尾结点处。

头结点尾结点依次向前,报到指定数删除cur指针指向的节点,未报到则每报一个数两个指针向前走一步,当cur节点自己指向自己时,cur指向节点的编码就是存活者的编号。

根据上述思路:先创建一个单向循环链表。

//定义节点
typedef struct SListNode {
    int val;//存编码
    struct SListNode* next;
} SLnode;

//创建节点
SLnode* Buynode(int i)
{
    SLnode* node=( SLnode*)malloc(sizeof(SLnode));
    if (node == NULL)
    {
        perror("malloc fail\n");
        return NULL;
    }
    node->val = i;
    node->next = NULL;
    return node;
}

//连接节点形成链表
SLnode* CreateSlist(int n)
{
    SLnode* phead = Buynode(1);
    
    SLnode* ptail = phead;
    for (int i = 2; i <= n; i++)
    {
        SLnode* tep = Buynode(i);
        ptail->next = tep;
        ptail = ptail->next;
        ptail->val = i;
     
       
    }
    ptail->next = phead;
    return ptail;

}

过程实现代码:

int main() {
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF) { // 注意 while 处理多个 case
        SLnode* ptail = CreateSlist(a);
        SLnode* prev = ptail;
        SLnode* phead = ptail->next;
        SLnode* cur = phead;
        while (cur->next != cur)
        {

            for (int i = 1; i < b; i++)//为什么从1开始,为什么是<b不是<=b.
            {
                cur = cur->next;//先前走
                prev = prev->next;

            }
            prev->next = cur->next;//删除节点
            free(cur);
            cur = prev->next;
        }
        // 64 位输出请用 printf(\"%lld\") to 
        printf("%d\n", cur->val);
    }
    return 0;
}

注意控制报数与指针走的步数的关系。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值