约瑟夫问题

Posted by serrini on March 30, 2020

约瑟夫问题

Question

N个人围成一圈,从第一个人开始报数,报到M的人出圈,剩下的人继续从1开始报数,报到M的人出圈;如此往复,直到所有人出圈。(模拟此过程,输出出圈的人的序号)

Answer

解法一: 假设有n个人,从1到n,放入一个ArrayList中。 设置开始的编号k(设为0,为第一个人),加上需要报的数减1,即得到需要出列人的索引。 要注意要出列的人是不是最后一个人,要特殊处理。当ArrayList为空,则完成。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Solution {

	public static void Josephus(int totalNum, int countNum) {
		List<Integer> start = new ArrayList<Integer>();
		for(int i=1; i<=totalNum; i++) {
			//初始化人数
			start.add(i);
		}
		
		int k = 0; 
		while(start.size() != 0) {
			k = k+countNum;
			k = k%(start.size())-1; //得到第m人的索引位置,所以要-1
			
			if(k == -1) {
				//到队尾
				System.out.println(start.get(start.size()-1));
				start.remove(start.size()-1);
				k = 0;
			}else {
				System.out.println(start.get(k));
				start.remove(k);
			}
		}
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner	= new Scanner(System.in);
		int totalNum = scanner.nextInt();
		int countNum = scanner.nextInt();
		Josephus(totalNum, countNum);
		scanner.close();
	}
}

//input:10 3
//output:3 6 9 2 7 1 8 5 10 4

解法二: 用队列

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Solution {

	public static void countQueue(int totalNum, int countNum) {
		Queue<Integer> queue = new LinkedList<Integer>();
		for(int i=1; i<=totalNum; i++) {
			queue.add(i);
		}
	
		int count = 0; //计数器
		while(!queue.isEmpty()) {
			int person = 0;
			person = queue.poll(); //出队列
			count++;
			if(count % countNum == 0) {
				//是,出队
				System.out.println(person);
			}else {
				//不是,继续入队列
				queue.add(person);
			}
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner	= new Scanner(System.in);
		int totalNum = scanner.nextInt();
		int countNum = scanner.nextInt();
		countQueue(totalNum, countNum);
		scanner.close();
	}

}