约瑟夫环问题的原来描述为,设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。 稍微简化一下。
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。
思路:容易想到的就是用环链表来做,构建一个环链表,每个结点的编号为0, 1, ...... n-1。每次从当前位置向前移动m-1步,然后删除这个结点。最后剩下的结点就是胜利者。给出两种方法实现,一种是自定义链表操作,另一种用是STL库的单链表。不难发现,用STL库可以提高编写速度。
源码:
package com.love.test;
import java.util.Scanner;
public class Demo4 {
private static class Node{
public int no;//编号
public Node next;//下一个节点
public Node (int no){
this.no =no;
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("总人数:");
int totalNum = input.nextInt();
System.out.println("请输入报数的间隔大小:");
int cycleNum = input.nextInt();
int sum=1;
Node header = new Node(1);
Node pointer = header;
for(int i = 2 ; i < totalNum;i++){
pointer.next=new Node(i);
pointer=pointer.next;
sum=sum+i;
}
pointer.next=header;//初始化环型链表
int sum1=0;
System.out.println("以下是出列的顺序---------------------------------");
while(pointer!=pointer.next){
for(int i = 1 ; i < cycleNum; i++){
pointer=pointer.next;
}
sum1= pointer.next.no+sum1;
System.out.println(pointer.next.no);
pointer.next = pointer.next.next;
}
System.out.println("---------------------------------------------------------");
System.out.println("总和:"+sum+"---------出列和:"+sum1+"---------------最后剩余一人:"+(sum-sum1));
}
}