约瑟夫环问题

来源:互联网 发布:淘宝复制宝贝 编辑:程序博客网 时间:2024/06/07 08:19

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。

从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;

依此规律重复下去,直到圆桌周围的人全部出列。

这是一个很常见的问题,在面试中经常出现。

考题应该分为两种:

1.考察出列人的顺序以及最后winner的序号

2.不考察出列人的顺序,只问最后winner的序号

面对第一种情况,令人最容易想到的就是,单循环链表实现。

首先构造一个具有n个节点的单循环链表,然后到第k个位置,开始循环。

每循环m次出来一个,最后剩下一个即为winner。

时间复杂度应该是O(m*(n - 1)),去掉常数为O(n)。

下面是我写的代码:

#include <stdio.h>
#include <stdlib.h>

typedef int elementype;
typedef struct node *pnode;
struct node
{
    elementype element;
    pnode next;
};

pnode creatlist(int num)
{
    pnode head,tmp;
    int i ;
    head = tmp = (struct node *)malloc(sizeof(struct node));
    if(head == NULL)
        return head;
    head->element = 1;
    for(i = 1;i < num;i++)
    {   
        tmp->next = (struct node *)malloc(sizeof(struct node));
        if(NULL == tmp)
        {
            printf("malloc error!\n");
            return NULL;
        }
        tmp = tmp->next;
        tmp->element = i + 1;
    }
    tmp->next = head;
    return head;
}

pnode delete(pnode p)
{
    pnode tmp;
    tmp = p->next->next;
    printf("the delete number is %d\n",p->next->element);
    free(p->next);
    p->next = tmp;
    return tmp;
}

pnode jose(pnode head,int m,int k)
{
    pnode tmp = head;
    int i;
    for(i = 1;i < k;i++)
        tmp = tmp->next;
    for(i = 1;;i++)
    {
        if(tmp->next == tmp)
            return tmp;
        if(i == m-1)
        {
            tmp = delete(tmp);
            i = 1;
        }
        tmp = tmp->next;
    }
}


int main(int argc,char **argv)
{
    int ret,i,n,m,k;
    pnode head;
    printf("Please input three number n m k:\n");
    ret = scanf("%d%d%d",&n,&m,&k);
    if(ret != 3 || n < 0 || m < 0 || k < 0)
    {
        printf("input the right number\n");
        return -1;
    }
    head = creatlist(n);
    head = jose(head,m,k);
    printf("the last winner is %d\n",head->element);
    return 0;
}

其实整个思路是非常清晰的,但是我写的代码太少了,在写代码的过程中

还是出现了很多问题。

1.创建循环单链表时,前一个node的next指针没有指向后一个node。这时应该

   自己画图。

2.在jose函数for循环中,没有添加循环条件,同样是因为自己代码写得太少了

另外有关如何解决约瑟夫问题第二种类型,有数学上的方法,没有必要去循环,

具体的内容,我以后再去研究。

原创粉丝点击