JAVA学习之路——约瑟夫环问题

Josephus problem简介

Josephus problem

又叫约瑟夫环问题,具体情况是是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

举例

有100个人围成一个圈(编号0-99),从第0号的人开始从1报数,凡报到3的倍数的人离开圈子,然后再数下去,直到最后只剩一个人为止,问此人原来的位置是多少号?

思路说明

首先根据问题,可以将这100人放入某一容器中,此容器可以是数组页可以是集合。然后开始进行数数,每次数到3的倍数时就将其中一个人移出容器,移出99个人之后,剩下的那个人就是我们想要知道号码的那个人。此问题,个人有如下两种实现方法。

链表实现

将数据放入链表中,并且转换为int型方便进行操作,声明了一个变量count作为计数工具。因为本例子中是每次数到3就将数据移出,最后只剩下一个元素时结束循环。

import java.util.LinkedList;

//约瑟夫环
public class Joseph {

	
	public static void main(String[] args) {
		LinkedList<Integer> x = new LinkedList<Integer>();
		for (int i = 0; i < 100; i++) {
			x.add(i+1) ;
		}
		
		int count = 1 ;
		for (int i = 0; i < x.size(); i++) {
			int j = x.get(i) ;//取出x集合中的数据
			if( count % 3 == 0 ){
				x.remove(i);
				i--;
			}else{
				int backvalue = x.pollFirst();//移除第一元素后,并且得到此元素
				x.offerLast(backvalue);//将之前移除的元素添加到此集合的末尾处
				i--;
			}
			count++;
			if(x.size()==1){
				break ;
			}
		}
		
		for (int i = 0; i < x.size(); i++) {
			System.out.println(x.get(i));
		}
	}
	
}

运行结果

91

数组实现

思路大体和链表实现的思路类似,但是数组无法将元素移出数组,所以在循环的时候将数到3倍数的数据置为0视为移出数组。而在下次循环的时候跳过数值为0的元素并且计数器不增加,在最后整个数组剩余数值不为0的元素只剩一个时结束循环

public class Joseph {

   	public void outArray(int []data,int num)
	{
		int i =0;
		int count = 0;//计数器
		int left = 100;//统计剩余数据的变量
		while(left!=1) {
			count++;
			i++;
			//此代码的作用是每次数到数值为0的元素时,计数器不变
			if(data[i-1]==0) {
				count--;
			}
			//计数器到3时元素出局,同时为了增加显示效果,输出了结果,也可以用if(count%3 == 0)作为判断条件,这样的话count不用清零
			if(3==count) {
				System.out.print("本次出局的是:"+data[i-1]);
				System.out.println();
				data[i-1]=0;
				count=0;
				left--;
			}
			//因为数组是线性的,所以当i到边界时得重新开始数
			if(100==i) {
				i=0;
			}
		}
		
		//执行完毕后,整个数组只剩一个不为0的元素,进行遍历将其输出
		for(i = 0;i<100;i++) {
			if(data[i]>0) {
				System.out.print("最后留下的是:"+data[i]);
			}
		}
	}
	public static void main(String[] args) {
		int [] data=new int [100];
		for (int j = 0; j < data.length; j++) {
			data[j]=j+1;
		}
       Joseph a = new Joseph();
       a.outArray(data, 100);
	}

}

总结

约瑟夫环问题并不算难,主要是需要明确该从何处着手实现每逢几的倍数就移出,想清楚关键点后,剩下的部分很容易就能写出来了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值