本人也是刚刚接触算法,如果有不准确的地方,欢迎大家留言评论,一起学习,一起进步,奥利给!
约瑟夫环的简单的图例(画的太抽象,大家理解下,我有必要去学学画画了!)
约瑟夫环的原理
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.youkuaiyun.com/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;
}
}
小剧场:几日不见,甚是想念啊