约瑟夫环之登山选队长问题(Java)

约瑟夫环:

N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。

  • 例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。
    123451234512345依次报数,6报完后回到1继续
    第一次报数:
    1【1】 2【2】 3【3】 4【4】 5【5】 6 (5被杀掉,留下1 2 3 4 6)
    第二次报数(上一次从1结束,因此此时从6开始继续报数):
    6【1】 1 【2】 2【3】 3【4】 5【5】(4被杀掉,留下1 2 3 6)
    第三次报数(上一次从4结束,因此此时从6开始继续报数):
    6【1】 1【2】 2【3】 3【4】 6【5】 (6被杀掉,留下 1 2 3)
    第四次报数(上一次从6结束,因此此时从1开始继续报数):
    1【1】 2【2】 3【3】 1【4】 2【5】 (2被杀掉,留下 1 3)
    第五次报数(上一次从2结束,因此此时从3开始继续报数):
    3【1】 1【2】 3【3】 1【4】 3【5】 (3被杀掉,留下 1)

登山选队长问题

  • 题目:
    今天同学们相约一起爬山游玩,为了更好的进行这场活动,大家准备推举一个人作为出游的临时队长。 为了体现合理公平,大家提出了一个比较有趣的规则:
    所有人围成一圈,顺序排号。从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子,剩下的人继续报数,最后留下的当选为队长。请你通过编写程序,求出一组人中的队长是原来第几位同学。
  • 思路:(与约瑟夫环同理)
    ①先输入同学(记为数组student)的人数N
    ②初始化:
    1)给定student数组默认初始值为1
    2)定义flag来记录报的数
    3)定义out来记录出圈的人数(当出圈人数为N-1时,表示只剩下最后一位同学,即队长)
    ③循环:(用i表示当前学生的下标)
    1)循环条件:当只剩下最后一位同学时结束循环,否则i++
    2)当student[i]=1时表示学生没有出圈,进行报数(flag++)
    3)当报到3(flag=3)时,出圈(student[i]=0),重新从1开始计数(flag=0,由于学生存在时才flag++,因此flag从0开始)
    4)如果下标i等于人数N,表明本轮循环结束,重新从头开始报数
    ④对student数组进行遍历,如果值为1(student默认为1,出圈记为0),则表示为剩下的最后一位同学,即为队长
  • 代码如下:
import java.util.Scanner;

public class Test {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入同学的人数:");
		int num = input.nextInt();//同学的人数
		int[] student = new int[num];
		for (int i = 0; i < student.length; i++) {
			student[i] = 1;//每个同学都为1,当退出圈子时记为0,方便接下来的判断
		}
		int flag = 0;//记录报数
		int out = 0;//记录出圈的人数
		int i = 0;//记录student的下标
		while(out != num - 1) {//当留下一位同学时,即为队长
			if(student[i] == 1) {
				flag ++;
			} 
			if(flag == 3) {
				student[i] = 0;//出圈,标记为0
				flag = 0;//重新开始报数
				out++;//出圈的人数+1
			}
			i++;
			if(i == num) {
				i=0;
			}
		}//end while
/*do-while循环也能实现(第一次写用的do-while,与while用法大同小异)
		do {
			if(student[i] == 1) {//该学生还没有退出圈子
				flag++;//
				if(flag == 3) {//数到3,出圈
					student[i] = 0; //出圈标记为0
					out ++;//出圈人数+1
					flag = 0;//继续从1开始(前面为flag++,故此处置为0)
				}
			}
			i++;
			if(i == num) {//如果是最后一位同学,则重新从头开始报数
				i = 0;
			}
		}while(out !=num - 1);//只剩下最后一位同学时,结束循环
*/
		for (int j = 0; j < student.length; j++) {
			if(student[j] != 0) {//退出圈子的同学为0,最后一位留在圈子中的同学为1
				System.out.println("队长为第" + (j+1) + "位同学");//下标从0开始,故第i位同学对应下标为j+1
			}
		}//end for
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selcouther

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值