约瑟夫问题升级版
编号为1~N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数,可以自由输入),开始人选一个正整数作为报数上限值M,从第一个人按顺时针方向自1开始顺序报数,报道M时停止报数。报M的人出列,将他的密码作为新的M值,从他顺时针方向上的下一个人开始从1报数,如此下去,直至所有人全部出列为止。
分析:
升级版的约瑟夫问题,就是在每个人的手中拿了一个密码,当这个人死了之后,拿着这个手中的密码,进行下一次剔除。
如上图所示,p 第一个拿到的是 3 ,则从头开始第 3 个人剔除,依次这样进行下去,直到所有人被剔除。
代码实现:
class JosephusLoopUpper {
private Node head; //头指针
private Node rear; //尾指针
private int size;
private int M; //每个人手中所拿的密码数字
public JosephusLoopUpper(ArrayList<Integer> list, int M){ //创建一个给定人个数的环
head=new Node(list.get(0),0,null); //创建第一个点 并将尾指向头形成一个环
rear=head;
rear.next=head;
for(int i=1;i<list.getSize();i++){ //创建给出个数的剩下的人(也就是一些结点)
rear.next=new Node(list.get(i),i,rear.next);
rear=rear.next;
}
size=list.getSize(); //获取环的长度
this.M=M; //每个人手中拿的密码数字
}
public void out(){ //开始操作,获取最后存活人的位置
Node p=head; //定义一个指针 p
while(size>0){
for(int i=1;i<=M-2;i++){ //拿着M密码 找出要删结点的前一个位置
p=p.next;
}
Node del=p.next; //创建一个结点del暂存一下要删除的结点
p.next=del.next;
p=p.next;
M=del.password; //将要删的结点的密码赋给M 进行下一次操作
System.out.print(del.position+" "); //打印出删除结点的位置
size--;
}
}
//创建结点的内部类 升级版比普通版多了一个密码password 参数而已
private class Node{
int password;
int position;
Node next;
public Node(){}
public Node(int password,int position, Node next){
this.password=password;
this.next=next;
this.position=position;
}
}
//主函数 加入一些结点给出参数即可
public static void main(String[] args) {
//3 1 7 5 0 6 4 2
ArrayList<Integer> list=new ArrayList<>();
list.addLast(3);
list.addLast(5);
list.addLast(3);
list.addLast(6);
list.addLast(3);
list.addLast(2);
list.addLast(4);
list.addLast(4);
JosephusLoopUpper ju=new JosephusLoopUpper(list,4);
ju.out();
}
}
来源:CSDN
作者:wyq小白
链接:https://blog.csdn.net/weixin_43294413/article/details/103717104