c语言 报数问题

题目描述:

有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

输入:

初始人数n

输出:

最后一人的初始编号

样例输入:

                                   3

样例输出:

                                   2

方法一:

分析:

    这个问题难点在于n个人围成一圈,要循环使用函数。 所以先设一个函数代表循环一次。先在主函数中
    设一个数组,都标记为0,然后传入函数中处理。然后给第三个标记为1,再重复,直到一次找完,同时
    记录下来剩余的人数,再循环,直到剩余一个人为止,然后在主函数中搜索标记为0的数的坐标输出。

代码:

#include

void findLast(int n,int number[],int j,int newn) //findLast函数求出最后一个数
{
   int i = 0;
   int newn1 = 0; //表示当前整数的个数

   newn1 = newn;
   for(i = 1;i <= n;i++)
   {
       if(0 == number[i])
       {
           j++;
       }
       if(3 == j)       //每次第三个数标为1,剩余newn1--个数
       {
           number[i] = 1;
           j = 0;
           newn1--;
       }
   }
   if(newn > 1)
   {
       findLast(n,number,j,newn1);  //如果剩余的数大于1,则继续循环
   }
}

int main45()
{
   int n = 0;
   int i = 0;
   int j = 0;
   int number[100] = {0};

   scanf("%d",&n);
   findLast(n,number,j,n);

   for(i = 1;i <= n;i++)    //数组中标为0的数的坐标为剩余的最后一个数原来的序号
   {
       if(0 == number[i])
       {
           printf("%d\n",i);
           break;
       }
   }
   return 0;
}

方法二:

分析:

     用环形链表解决,环形链表是将单链表的头和尾连接起来,解决报数问题更方便。

代码:

#include
#include

typedef struct st_number
{
    int number;
    struct st_number *next;
}Number,*Numberp;         // 定义结构体

/**********************************************************************************
函数名称:creatlist
描述:创建一个链表
参数:链表的长度peoplenumber
返回值:返回头结点
**********************************************************************************/

Numberp creatlist(int peoplenumber)
{
    Numberp head;
    Numberp list;
    Numberp q;
    int i = 0;

    head = (Numberp)malloc(sizeof(Number));
    head->number = NULL;
    head->next = NULL;
    q = head;         // 创建头结点

    for(i = 1;i <= peoplenumber;i++)
    {
        list = (Numberp)malloc(sizeof(Number));
        list->number = i;
        q->next = list;
        q = list;
    }          // 创建链表并赋值
    q->next = head;  // 将链表的尾和头连接起来,形成环形链表
    return head;
}

/**********************************************************************************
函数名称:findLast
描述:求剩余的最后一个数并输出
参数:创建的链表numberlist,总人数peoplenumber
返回值:无
**********************************************************************************/

void findLast(Numberp numberlist,int peoplenumber)
{
    int count = 0;
    Numberp temp;     // 创建临时指针

    numberlist = numberlist->next;   // 跳过头结点
    while(peoplenumber != 1)
    {
        if(numberlist->number != NULL)
        {
            count++;       // 计数
            if(2 == count) // 如果到第二个就删除下一个结点
            {
                temp = numberlist->next;
                if(temp->number == NULL)
                {
                    temp = temp->next;  // 如果是头结点就跳过
                }
                numberlist->next = temp->next;
                free(temp);
                count = 0;
                peoplenumber--;
            }
        }
        numberlist = numberlist->next;
    }
    numberlist = numberlist->next;

    printf("%d\n",numberlist->number);  // 输出剩余的最后一个数
}

int main45()
{
    int peoplenumber = 0;
    Numberp numberlist;

    scanf("%d",&peoplenumber);
    numberlist = creatlist(peoplenumber);
    findLast(numberlist,peoplenumber);

    free(numberlist);
    return 0;
}

你可能感兴趣的:(c语言)