约瑟夫环问题的两种解决方式(递归求解和数组模拟求解)

约瑟夫环问题各位Acmer肯定都遇到过,就是给你编号为从0~n-1的n个人,从头开始报数,报到m的人离场,问最后留下的人是几号。有两种方法解决这个问题

第一种:数组模拟

这种方法没什么好说的,就是模拟报数和离场的过程,加个访问数组标记一下谁离场了就好了

package HomeWork;

public class JosephRing1 {

	public static int josephring(int a[]){

		int vis[] = new int [17];
		int ans = 0;
		int cnt = 0;
		int i = 0;
		while(true){
			if(i == 17){
				i = 0;
			}
			if(vis[i] == 0){	
				cnt++;
				if(cnt % 3 == 0){
					vis[i] = 1;
					ans++;
					System.out.printf("第%d次离开的人是:%d\n",ans,a[i]);
					if(ans == 16)
						break;
				}
			}
			i++;
		}
			for(i=0;i<17;i++){
				if(vis[i] == 0)
					break;
			}
			return a[i];
		}

		public static void main(String [] args){

			int ans = 0;
			int a[] = new int [17];
			for(int i=0;i<17;i++){
				a[i] = ans++;
			}

			System.out.println("最后留下的是:" + josephring(a) + "号");
		}

	}


第二种:递归求解

感觉数组模拟实在low的一批,所以还有一种数学思想的求法;

我们通过写几组简单数据来发现一些规律,比如有6个人,他们编号分别是0,1,2,3,4,5,规定数到3的人离开,那么首轮离开的是2,5,第二轮离开的是3,也就是说离开人的编号是(m-1)%n,下一轮编号为0的人是(m + 0)%n,下一轮编号为1的人是(m+1)%n,则下一轮编号为i的人是(m+i)%n。我们设函数X(n)表示n个人中离开的人,则根据关系有X(n) = (m+X(n-1))%n,那么我们就得到了一个递归表达式,终止递归的条件是x(1),x(1) = (n+m-1)%n。

package HomeWork;

public class JosephRing2 {
	
	public static int josephring2(int n,int m,int i){
		
		if(i == 1){
			return (n + m-1) % n;
		}
		else{
			return (josephring2(n-1,m,i-1) + m) % n;
		}
	}
	
	public static void main(String [] args){
		
		for(int i=1;i<=16;i++){
			System.out.printf("第%d次离开的人是:%d\n",i,josephring2(17,3,i));
		}
		System.out.printf("最后留下的人是:%d\n",josephring2(17,3,17));
	}
}

可以看到结果是一样的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值