A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

原题目为:耶稣有15个门徒,其中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:15人围坐一圈,从第一个开始报号:1,2,3,1,2,3……,凡是报到“3”就退出圈子,最后留在圈内的人就是出卖耶稣的叛徒,请找出它原来的序号。
这个有很多中解决方法,但是为了能解决同类型的问题(比如30个门徒,报到5就退出),我使用了单向循环链表:
/*
* 15人围成一圈,从第一个开始报数:1,2,3,1,2,3······,凡是报到“3”就退出圈子,
* 找出最后留在圈内的人原来的序号
* 最直接方法,就是利用单循环链表
*/

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


#define M 15
#define N 3


struct node {
    int value;
    struct node *next;
};


struct node *add_to_list(struct node *list, int n);
struct node *finding(struct node *list1, struct node *list2);


int main(void)
{
    struct node *first = NULL;
    struct node *end = NULL;
    int i;


    end = first = add_to_list(first, M);
    for (i = M-1; i > 0; i--)
        first = add_to_list(first, i);
    end->next = first;


    printf("%d\n", finding(first, end)->value);


    return 0;
}


struct node *add_to_list(struct node *list, int n)
{
    struct node *new_node;


    new_node = malloc(sizeof(struct node));
    if (new_node == NULL) {
        printf("Error: malloc failed in add_to_list\n");
        exit(EXIT_FAILURE);
    }
    new_node->value = n;
    new_node->next = list;


    return new_node;
}


struct node *finding(struct node *list1, struct node *list2)
{
    int i = 0;
    struct node *curr, *prev;


    prev = list2;
    curr = list1;
    for (;;) {
        if (prev == curr)
            return curr;
        i++;
        if (i == N) {
            prev->next = curr->next;
            curr = curr->next;
            i = 0;
            continue;
        }
        prev = prev->next;
        curr = curr->next;
    }
}
只需要更改宏M和N的值,即可使用与所有的情况(希望版主加分,我马上就够25技术分了)。

10 个回复

倒序浏览
想屎。。。根本看不懂  我还能不能愉快的培训了
回复 使用道具 举报
本以为我的代码就很复杂了 你是大神 你厉害~~~~:L

回复 使用道具 举报
liyang783 来自手机 中级黑马 2015-3-11 22:35:31
板凳
挺好的。就是一点注释没有,看着费劲。
回复 使用道具 举报
这么巧啊,我也有这道题。费了不少功夫
回复 使用道具 举报
以前做过一个选猴王的题跟这个类似
回复 使用道具 举报
int a[15];
    int num=0;
    int count=0;
    for (int i=0; i<15; i++) {
        a[i]=0;//1代表遇到3出局
    }
    while(1){
        for (int i=0; i<15; i++) {
            if (a[i]==0) {
                num++;
                if(num==3){
                    a[i]=1;
                    num=0;
                    count++;
                }
            }
        }
        if((15-count)<3) //剩余数不够3个,跳出while循环
            break;
    }
    for (int i=0; i<15; i++) {
        if(a[i]==0)
            printf("%d\n",i+1);
    }
答案是5和14吧?
回复 使用道具 举报
still过客 发表于 2015-4-23 20:04
int a[15];
    int num=0;
    int count=0;

5和14也是要继续这样的。。。
回复 使用道具 举报
  1. /*
  2. 耶稣有15个门徒,其中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:
  3. 15人围坐一圈,从第一个开始报号:1,2,3,1,2,3……,凡是报到“3”就退出圈子,
  4. 最后留在圈内的人就是出卖耶稣的叛徒,请找出它原来的序号。
  5. */
  6. #include<stdio.h>
  7. #include<stdlib.h>
  8. typedef struct _node{
  9.         int num;
  10.         struct _node *next;
  11. }Node;

  12. typedef struct _list{
  13.         Node *head;
  14.         Node *tail;
  15. }List;


  16. int main(){
  17.         List list;
  18.         list.head = list.tail = NULL;
  19.         int i;

  20.         for (i =0; i < 15; i++){               
  21.                         Node *p = (Node *)malloc(sizeof(Node));
  22.                         p->num = i + 1;
  23.                         p->next = NULL;
  24.                 if (list.tail){       
  25.                         list.tail->next = p;
  26.                         list.tail = p;
  27.                 }else {
  28.                         list.head = list.tail = p;
  29.                 }
  30.                
  31.         }
  32.         list.tail->next = list.head;
  33.         Node *p = list.head;
  34.         Node *q = NULL;
  35.         int count = 0;
  36.         for (i = 2; ; i++){
  37.                 q = p;
  38.                 p = p->next;
  39.                 if (p->next == p){
  40.                         printf("last = %d", p->num);
  41.                         break;
  42.                 }
  43.                 if (i % 3 == 0){
  44.                         q->next = p->next;
  45.                         count++;
  46.                         printf("delete%d\n", p->num);
  47.                 }
  48.         }       
  49.         return 0;
  50. }
复制代码


结果是5
回复 使用道具 举报
这,教我如何安心学习。。。。
回复 使用道具 举报
  1. /*
  2. 程序思想:每次往前数三个数第三个数即为当前出队的数,将出队的数置为-1
  3. 当数间隔遇到为-1的数时不计入步长,每次循环完一次总长度减1,直到长度为1,
  4. 值不为-1的数就为答案
  5. */

  6. #include <stdio.h>

  7. int FindJuda(int per[], int start)
  8. {
  9.         int count = 0, length = 15;
  10.         start = start - 1;//数组从0开始,所以开始下标需要减1

  11.         while (length != 1)
  12.         {
  13.                 while (count != 3)
  14.                 {
  15.                         if (per[start] != -1)
  16.                         {
  17.                                 count++;

  18.                                 if (count != 3)
  19.                                 start = (start + 1) % 15; //控制循环从0-14
  20.                         }
  21.                         else
  22.                         {
  23.                                 start = (start + 1) % 15;
  24.                         }
  25.                 }
  26.                 length--;
  27.                 printf("Out people number: %d\n", per[start] + 1);
  28.                 per[start] = -1;
  29.                 start = (start + 1) % 15;
  30.                 count = 0;
  31.         }

  32.         for (count = 0; count < 15; count++)
  33.         {
  34.                 if (per[count] != -1)
  35.                         return per[count] + 1;
  36.         }
  37. }

  38. int main()
  39. {
  40.         int person[15], start;
  41.         int i = 0, juda;

  42.         //初始化数组0-14,代表每个人的编号
  43.         for (i = 0; i < 15; i++)
  44.         {
  45.                 person[i] = i;
  46.         }

  47.         printf("Please input start number:");
  48.         scanf ("%d", &start);

  49.         juda = FindJuda(person, start);//执行函数找出叛徒
  50.         printf("The Juda is number: %d\n", juda);

  51.         return 0;

  52. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马