Java 约瑟夫环问题的两种解法(循环数组,单向环形链表)

1.问题

Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

2.解决方法一:循环数组

提示:每次报数,如果满足出圈的条件就将数组元素设置为-1,当下次报数时跳过-1。直至数组最后一个元素变为-1,循环结束,数组的循环使用取模来完成。
解决

//解决方法二:数组+取模
public static void JosephuByArr(int total,int startNum,int m){
	int []Arr=new int[total];
	int leave=total;                           //剩下的数量
	int count=0;                               //报数(0-1-2-3-4-5····)
	int index=startNum;                        //第一个元素
	//初始化数组(为了方便取模,最后一个元素放在数组的第0个,也可以先加一再取模)
	Arr[0]=total;
	for(int i=1;i0){
		count++;                               //报数
		//找到报数为count的数组元素
		if(Arr[index%total]==-1){
			while(Arr[index%total]==-1){
				index++;
			}
		}
		//如果满足条件,输出(元素设置为-1)
		if(count%m==0){
			System.out.print(Arr[index%total]+"\t");
			Arr[index%total]=-1;
			leave--;
		}
		//下一个元素开始
		index++;
	}
}

3.解决方法二:单向环形链表

提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
单向环形链表的构建:

class CNode{
	private int val;
	private CNode next;
	public CNode(int val) {
		super();
		this.val = val;
	}
	
	public CNode() {
		super();
	}

	public int getVal() {
		return val;
	}
	public void setVal(int val) {
		this.val = val;
	}
	public CNode getNext() {
		return next;
	}
	public void setNext(CNode next) {
		this.next = next;
	}

	@Override
	public String toString() {
		return val+"\t";
	}
	
}

//创建一个单向环形链表
class CircularList{
	private CNode first=null;       //环形链表的首部
	private int length;             //环形链表长度
	
	//创建约瑟夫环
	public void create(int num){
		if (num<1) {
			System.out.println("num值不正确");
			return;
		}
		CNode pre=null;                   //帮助构建环形链表 
		for(int i=1;i<=num;i++){
			CNode tmp=new CNode(i);
			if(i==1){
				first=tmp;
				first.setNext(first);
				pre=tmp;
				length++;
			}
			else{
				pre.setNext(tmp);
				tmp.setNext(first);
				pre=tmp;
				length++;
			}
		}
	}

	//遍历单向链表
	public void list(){
		if(first==null){
			System.out.println("链表为空");
			return;
		}
		CNode tmp=first;
		while(true){
			if(tmp.getNext()==first){
				System.out.print(tmp);
				break;
			}
			System.out.print(tmp);
			tmp=tmp.getNext();
		}
	}
	
	//根据索引获取结点
	public CNode getCNodebyIndex(int index){
		index=index%length;
		if(index==0){
			index=length;
		}
		CNode cur=first;
		for(int i=1;i

解决:

//解决方法一:使用单向环形链表
public static void JosephuByCL(int total,int startNum,int m){
	//创建单向环形链表
	CircularList CL=new CircularList();
	CL.create(total);
	
	//count作为报数值,若为m的倍数就输出并删除,直到所有结果均输出,结束
	CNode tmp=CL.getCNodebyIndex(startNum);  //初始化startNode
	int count=0;
	while(CL.getLength()>0){
		count++;
		if(count%m==0){
			System.out.print(tmp);
			CL.del(tmp);
		}
		tmp=tmp.getNext();
	}
}

你可能感兴趣的:(数据结构与算法,Java学习)