约瑟夫环代码展示,以及理解约瑟夫环

本人也是刚刚接触算法,如果有不准确的地方,欢迎大家留言评论,一起学习,一起进步,奥利给!

约瑟夫环的简单的图例(画的太抽象,大家理解下,我有必要去学学画画了!)

约瑟夫环的原理

1、一群人围在一起坐成环状(如:N)

2、从某个编号开始报数(如:K)

3、数到某个数(如:M)的时候,此人出列,

4、一直循环,直到所有人出列

不够清晰的话,可以看我上边优秀的画图,一群人N指的就是11,摸个编号开始报数K指的就是数字1(但是记住,他的下标是0哦~~~~~~~~),第一次数到某个数指的就是3,第二次数到某个数指的是6,以此类推哦----------,一直循环,直到所有的人都出列指的是N变为0,就是没人了,出列也就出完了。

简单的约瑟夫环问题(1)

已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1(指的是下标),最后 结果+1(因为我们找的是下标对应的这个数,所以要加 1 哦)即为原问题的解。

代码分析

import java.util.Scanner;

public class 约瑟夫环 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt()
        int k = sc.nextInt();
        int p = 0;
        for (int i = 2; i <= n; i++) {
            p = (p + k) % i;
        }
        System.out.println(p + 1);
    }
}

约瑟夫环最经典的问题(2)

       据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

看完这道题我的第一反应居然不是去解题,而是感慨,那个人真是编程天才,机智的一批,更想说的是不要仅仅指望知识来吃饭,关键时刻,知识能救命的呀!

题目分析

把这道题上相应的数字带入到上面约瑟夫环的原理的分析中。

代码分析,代码学习的位置、https://blog.csdn.net/weixin_43570367/article/details/105896737?utm_source=app

package 约瑟夫环问题;

import java.util.Scanner;

public class 约瑟夫环问题 {

	public static void main(String [] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		
		if(n<2) {
			System.out.println("请您输入大于二的数字:");
			return ;
		}
		//构建链表并获取头结点,把头节点赋值给currentNode
		Node currentNode = buildData(n);
		//用来计数
		int count =0;
		//循环链表当前节点的上一个节点
		Node beforeNode = null;
		//循环遍历列表
		while(currentNode!= currentNode.next) {
			count++;
			if(count == 3) {
				//向后移动节点
				beforeNode.next = currentNode.next;
				System.out.println("出环的标号是:"+ currentNode.data);
				count = 0;
				currentNode = currentNode.next;
			}else
			{
				//向后移动节点
				beforeNode = currentNode;
				currentNode = currentNode.next;
			}
			//表示只有两个节点了,不在进行出环操作
			
			
			if(beforeNode.data == currentNode.next.data) {
				
				break;
			}
		}
		
		System.out.println("最后留在环中的标号是:"+currentNode.data+ ","+ currentNode.next.data);
	}
	
	
	/*
	 * 构建单项循环链表
	 * @param  n 人数
	 * 
	 * @return返回头节点
	 * */
	
	private static Node buildData(int n) {
		//循环链表的头节点
		Node head = null;
		//循环链表当前节点的前一个节点
		Node prev  = null;
		
		for(int i=1; i<=n ; i++) {
			Node newNode = new Node(i);
			//如果是第一个节点
			if(i == 1) {
				head = newNode;
				prev = head;
				//跳出当前循环,进行下一次循环
				continue;
			}
			//如果不是第一个节点
			prev.next = newNode;
			prev = newNode;
			//如果是最后的一个节点
			if(i == n) {
				prev.next = head;
			}
			
		}
		return head;
	}
	
}
class Node{
	//当前存储的数据
	int data;
	Node next;
	//当前节点的下一个节点
	
	public Node(int data) {
		this.data = data;
	}
}

小剧场:几日不见,甚是想念啊

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值