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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

5黑马币
50个人围成一圈数到三和三的倍数时出圈,问剩下的人是谁?在原来的位置是多少?

30 个回复

正序浏览
本帖最后由 JiangHG 于 2015-3-14 11:43 编辑

此问题可用循环链表模拟,节点的num存储信徒的序号,用一个变量暂存所报的序号,如果是3则将这个节点从链表中下链。
#include <stdio.h>
#include <malloc.h>
#define MAX 50 //人数

typedef struct student {
    int num;
    struct student *next;
}s_list;
/* 创建循环链表 */
s_list *creat_list()
{

    s_list *head = NULL;
        s_list *p = NULL;
        s_list *q = NULL;
    int i = 0;
        /* 申请头节点的存储空间 */
    head = p = (s_list *)malloc(sizeof(s_list));
        if (NULL == head)
        {
                printf ("malloc error!");
                return;
        }
    p->num = 1;// 序号
        /* 初始化第二到最后面的序号*/
    for (i = 2;i <= MAX; i++)
        {
        q = (s_list *) malloc(sizeof(s_list));
                if (NULL == q)
                {
                        printf ("malloc error!");
                        return;        
                }
        q->num = i;
        p->next = q;
                p = q;
    }
        /* 由于循环链表 将最后一个节点的next指向头*/
    p->next = head;

    return(head);
}
/* 执行报数的流程 */
s_list *del_people(s_list* head)
{

    s_list *p1 = head;
        s_list *p2 = head;
        s_list *del_node = NULL;
    int k = 1; //用于记录当前所报的数

    while(p1->next != p1) //只有一个人
        {
        if(k == 3) /* 报到三则下链 */
                {   
            del_node = p1; //标记要删除的节点
                        /* 下链并释放 */
            p1 = p1->next;
            p2->next = p1;
            free(del_node);
            del_node = NULL;
            k = 0;
        }
                else
                {
            p2 = p1;
            p1 = p1->next;
        }
        k++;
    }
    p1->next = NULL;
    return(p1);
}
/* 打印最后的叛徒序号 */
void print_alive_pelple(s_list *head)
{
        s_list *p = NULL;
        if (NULL == head )
        {
                return;
        }
    printf("alive num is %d\n",head->num);

}
/* 主函数 */
int main()
{
    s_list *head = NULL;
        s_list *alive_node = NULL;
    /* 创建并初始化一个循环链表 */
    head  = creat_list();
        /* 报号并退出出的执行 */
    alive_node = del_people(head);
        /* 输出最后的叛徒 */
    print_alive_pelple(alive_node);
        /* 释放链表 防止内存泄漏 */
    free(alive_node);
        alive_node =  NULL;
    return 0;
}
回复 使用道具 举报
顶一个:)
回复 使用道具 举报
ArrayList  在迭代时,判断,使用递归比较方便
回复 使用道具 举报
这是纯粹的数学问题,11和43
回复 使用道具 举报
学习了   膜拜大神     感觉自己好菜呀
回复 使用道具 举报
郑飞 高级黑马 2014-11-21 15:02:05
25#
本帖最后由 郑飞 于 2014-11-21 15:04 编辑

原创;P 就用了1个for2个if 还算比较简便 思路也不难 咱新手就图个思路 并不是为解题而解题 希望对楼主有帮助
  1. class Test
  2. {
  3.         /*
  4.         *50长度元素值全1的数组1个
  5.         *count不断循环数组并累加所有元素值;
  6.         *count逢3时,元素值改为0(为了下次count访问并累加该元素时不计数,count的存在就是为了逐步把每个元素值都改为0);
  7.         *这时update++(因为count遇到3的倍数了,update记录);
  8.         *当update为50的时候说明找到最后一个元素,返回角标+1;
  9.         **/
  10.         public static void main(String[] args)
  11.         {
  12.                 int[] arr = new int[50];
  13.                 for(int i = 0;i<50;i++)
  14.                         arr[i] = 1;//定义一个长度50,元素值都为1的数组;
  15.                 for(int i =0,count = 0,update = 0;;i++)//上面说的很清楚了
  16.                 {
  17.                         i = i==50?0:i;//从角标0开始不断循环访问数组所有元素(i=50就重置为0);
  18.                         //如果上次count值不能被3整除,并且本次count能被3整除,说明该位置是1(0代表);
  19.                         if(count%3!=0&(count+=arr[i])%3==0)
  20.                         {
  21.                                 arr[i]=0;//元素值改为0,让count无视它
  22.                                 update++;//记录本次被3整除时事件
  23.                         }
  24.                         if(update==50)//当遇到50次被3整除后,说明最后一次访问的就是数组最后一个值为1的元素
  25.                         {
  26.                                 System.out.println(i+1);//放回角标+1(位置)
  27.                                 break;
  28.                         }
  29.                 }
  30.         }
  31. }
复制代码
回复 使用道具 举报
ganjx 发表于 2014-10-22 23:31
此题主要还是考查我辈的基本功了,我就直接贴代码,最后打印出11,43; ...

N,厉害,赞一个!!!
回复 使用道具 举报
菜鸟路过,学习下。
回复 使用道具 举报
暴君 中级黑马 2014-11-12 19:18:56
22#
不是很懂,但是个人感觉猴子那个更好点,毕竟没有写死,可以套用
回复 使用道具 举报
zsfy 初级黑马 2014-11-9 22:28:11
21#
#include <stdio.h>
int main()
{
        int k=0,j=0;
        int name[50];
        for (int m=0;m<50;m++)             //给数组编号,1~50 此时m=50
        {
                name[m]=m+1;
        }
        for (int i=m;i>1;)                                //i 表示人数,此时m=50
        {
                if (name[j]!=0)
                {
                        k++;
                }
                if (k==3)                                  //k为报数值,       
                {
                        name[j]=0;                  //此时将此人的值赋值为0,表示此人已经排除
                        k=0;                                 //重新赋值给k
                        i--;                                 //人数减1
                }
                j++;
                if(j==m)
                {
                        j=0;              //由于是围成一圈,当j的值等于15时,将其设置为0
                }
        }
        for (int n= 0; n< m; n++)
        {
       if (name[n] > 0)               //最后一个不为0的数字编号即为叛徒的编号
                {
            printf("出卖耶稣的叛徒的原来序号是%d\n",name[n]);
        }
    }
        return 0;
}
回复 使用道具 举报
//此算法可以求出剩下的那个人的位置和序号
import java.util.LinkedList;   
import java.util.List;   
//测试类   
public class Cycle {      
    public static int cycle(int total, int k) {  //功能方法   
        List<Integer> dataList = new LinkedList<Integer>();//创建链表对象   
        for (int i = 0; i < total; i++)  //添加数据元素   
            dataList.add(new Integer(i + 1));      
        int index = -1;  //定义下标,模拟已经去掉一个元素,因此从-1开始  
    while (dataList.size() > 1) { //一直循环去除数据,直到只剩下一个元素   
            index = (index + k) % dataList.size();//得到应该出局的下标   
            dataList.remove(index--);  //去除元素   
        }      
        return ((Integer) dataList.get(0)).intValue();//返回它的值   
    }      
  //主方法   
    public static void main(String[] args) {      
        System.out.println("该数字原来的位置是:"+cycle(50, 3));     
    }      
}  
回复 使用道具 举报
yuanlingqi 发表于 2014-11-8 13:42
50个人围成一圈,形成一个闭环,这个一个典型的链表结构,每次出圈,只要把出圈人的左右对接即可,链表最后 ...

从1开始编号和数数,50人最后剩下的是11号
回复 使用道具 举报
本帖最后由 yuanlingqi 于 2014-11-8 13:49 编辑

50个人围成一圈,形成一个闭环,这个一个典型的链表结构,每次出圈,只要把出圈人的左右对接即可,链表最后剩下的那个人,就是你想要的。不多说上代码:
  1. //先要有个用户,包含三个属性
  2. package cn.csdn.test;

  3. public class User {
  4.     /**
  5.      * 用户id
  6.      */
  7.         private int userId;
  8.         /**
  9.          * 下个用户
  10.          */
  11.         private User next;
  12.         /**
  13.          * 上个用户
  14.          */
  15.         private User pre;
  16.        
  17.         public User(int no) {
  18.                 this.userId = no;
  19.         }
  20.         public int getUserId() {
  21.                 return userId;
  22.         }
  23.         public void setUserId(int userId) {
  24.                 this.userId = userId;
  25.         }
  26.         public User getNext() {
  27.                 return next;
  28.         }
  29.         public void setNext(User next) {
  30.                 this.next = next;
  31.         }
  32.         public User getPre() {
  33.                 return pre;
  34.         }
  35.         public void setPre(User pre) {
  36.                 this.pre = pre;
  37.         }
  38. }
复制代码
2.游戏开始
  1. package cn.csdn.test;
  2. import cn.csdn.test.User;
  3. public class GamePlay {
  4.         
  5.         /**
  6.          * 出圈数数
  7.          */
  8.         private static int OUTNUMBER = 3;
  9.         /**
  10.          * 玩游戏的人数
  11.          */
  12.         private static int USERCOUNT = 5;
  13.         
  14.         public static void main(String[] args) {

  15.                 if(USERCOUNT <= 0 || OUTNUMBER <= 0) {
  16.                         System.out.println("你逗我?");
  17.                         System.exit(-1);
  18.                 }
  19.                
  20.                 //1.将50个人围成一圈,构成单向链表结构
  21.                 User firstUser = null,curUser = null,newUser = null;
  22.                 for(int i=1; i<=USERCOUNT;i++){
  23.                         newUser = new User(i);
  24.                         if(firstUser == null){
  25.                                 firstUser = newUser;
  26.                                 curUser = newUser;
  27.                         }else{
  28.                                 newUser.setPre(curUser);
  29.                                 curUser.setNext(newUser);
  30.                                 curUser = newUser;
  31.                         }
  32.                 }
  33.                 //形成闭环
  34.                 curUser.setNext(firstUser);
  35.                 firstUser.setPre(curUser);
  36.                
  37.                 //2.从头开始遍历链表,数到3的人出链表,再将出圈人的左右两人对接
  38.                 User temp = firstUser;
  39.                 int i = 1;
  40.                 do{
  41.                         if(temp != null && i % OUTNUMBER == 0){
  42.                                 User pre = temp.getPre();
  43.                                 User next = temp.getNext();
  44.                                 if(next == pre) {
  45.                                         temp = next;
  46.                                         break;
  47.                                 }
  48.                                 pre.setNext(next);
  49.                                 next.setPre(pre);
  50.                                 temp = next;
  51.                                 i=1;
  52.                         }else{
  53.                                 temp = temp.getNext();
  54.                                 i++;
  55.                         }
  56.                 }while(true);
  57.                 System.out.println("共有"+ USERCOUNT + "玩家,最后留在圈的人是  " + temp.getUserId());
  58.         }
  59. }
复制代码




回复 使用道具 举报
路过看看
回复 使用道具 举报
请楼主仔细看16楼 中我想这个应该是最标准的算法了(猴子选大王算法)
里面你要求是50人 我这里都没规定死 我是基于算法本身,变量不写死。这个方法就可以单独做成类。方便以后调用。也就是说 以后遇到不是人数是50 第3人或3的倍数(也就是被3整除=0)出局的时候 可以套用。。这是个公式。。就跟真理是已经经过多代人验证过一样,与其说是帮你解决这问题 不如说是教你认识一种前人验证好了的方法,我们要记住以后遇到类似的问题 不用去研究新算法 改怎么实现,直接拿过来套用 笔着  葫芦画瓢,节省时间久是节省金钱

评分

参与人数 1黑马币 +6 收起 理由
void + 6

查看全部评分

回复 使用道具 举报
/*
根据你的需求 这里用到了一个关于数组的 古典游戏“猴子选大王”的算法
参选的人按1 2 3......n编号并按顺序围成一圈,由第K人(这里K可以根据个人要求指定)开始从1报数
报数到达P时跳出圈外,再由下一个人从1开始 如此循环 知道剩下最后一人 这人也就是(猴子选大王算法中的王)我们所需要的人
*/
import javax.swing.JOptionPane

public class PersonKing{
        public static void main(String[] args){
                String s;
                int n, k, p,n1;
               
                s=JOptionPane.showInputDialog("请输入人数的总数");
                n=Integer.parseInt(s);
                n1=n+1;
                s=JOptionPane.showInputDialog("请输入起始报数人的编号");
                k=Integer.parseInt(s);
                s=JOptionPane.showInputDialog("请输入出局数字: ");
                p=Integer.parseInt(s);
                int a[]=new int[n+1];
                a[0]=0;
                System.out.println("\t 出局人的编号: ");
                for(int i=1;i<a.length;i++)
                        a[i]=1;
                for(int i=1;i<=p;i++){
                        if(n==1)
                                break;
                        else if(i==p||i/3==0){
                                n--;
                                i=0;
                                a[k]=0;
                System.out.print(k+" ");

                        }
                        do{
                        k++;
                        k=k%n1;
                        }where(a[k]!=1);
                }       


                System.out.println("\n 最后剩余的人的编号为:"+k);
               
        }
}
回复 使用道具 举报
本帖最后由 渐行渐远 于 2014-11-3 22:46 编辑

import java.util.ArrayList;
import java.util.List;
public class ZhuanQuan {

        public static void main(String[] args) {
                //创建数组型队列
                ArrayList<Integer>al=new ArrayList<Integer>();
                for(int i=1;i<=50;i++){
                        al.add(i);//添加元素
                }
                while(al.size()>1){       //剩最后一人时停止
                        for(int j=0;j<3;j++){                                 
                               int x=al.remove(0);//将点到的人取出
                               if(j%3!=2){   
                                        al.add(x); //不是3的倍数再加到队尾
                                }
                        }
                                                
                }
                System.out.println("最后一个人是"+al.get(al.size()-1));
        }

}
回复 使用道具 举报
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. typedef struct LinkNode linkNode;

  4. //创建一个结构体,用来表示每个节点
  5. struct LinkNode {
  6.     //每个节点的编号
  7.     int id;
  8.     //这个节点的下一个的地址
  9.     linkNode *next;
  10. };


  11. int main()
  12. {
  13.     //初始化第一个节点。设置变量当前节点和下一个节点
  14.     linkNode *head = NULL , *tempCurrent,*tempNext;
  15.    
  16.         //创建节点
  17.         //创建第一个节点
  18.         tempCurrent = (linkNode *)malloc(sizeof(linkNode));
  19.         head = tempCurrent;
  20.         head -> id = 1;
  21.         //创建之后的节点
  22.         for (int i = 2; i <= 50; i ++) {
  23.             //分配节点大小
  24.             tempNext = malloc(sizeof(linkNode));
  25.             
  26.             tempNext -> id = i;
  27.             tempCurrent -> next = tempNext;
  28.             tempCurrent = tempNext;
  29.         }
  30.         //循环链表
  31.         tempCurrent -> next= head ;
  32.    

  33.    
  34.     linkNode *replace = head,*temp = NULL;
  35.     //查找要去除的点,直到还剩最后一个点
  36.     while (replace -> next != replace) {
  37.         
  38.         //设置间隔数量,不是间隔数就直接跳过,直到找到间隔数的节点
  39.         for (int j = 1; j < 3; j ++) {
  40.             temp = replace;
  41.             replace = replace -> next;
  42.         }
  43.         
  44.         //去除满足要求的点
  45.         temp -> next = replace -> next;
  46.         
  47.         printf("出局的是 %d\n",replace -> id);
  48.         //释放节点内存
  49.         free(replace);
  50.         //临时变量向后移
  51.         replace = temp -> next;
  52.     }
  53.    
  54.     //找出最后剩下的点
  55.     printf("最后还剩下的是 %d\n",replace -> id);
  56.     return 0;
  57. }
复制代码
C语言写的,望采纳

回复 使用道具 举报
ganjx 中级黑马 2014-11-2 17:30:41
12#
邵起 发表于 2014-11-2 09:09
楼主的意思不是只剩一个人吗。。。

谢谢指出问题,第二十二行改为下面的即可,最后输出11
  1. while(flag>=2)
复制代码



回复 使用道具 举报
ganjx 发表于 2014-10-22 23:31
此题主要还是考查我辈的基本功了,我就直接贴代码,最后打印出11,43; ...

楼主的意思不是只剩一个人吗。。。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马