问题描述:
Josephu 问题:设编号为1,2,n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,报到m的出列, 它的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止。得到最后一个出列的人或者出列顺序
import java.util.ArrayList;
/**
* Josephu 问题:设编号为1,2,n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,报到m的出列,
* 它的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止。得到最后一个出列的人或者出列顺序
*
* 方法:
* 1. 单向循环链表
* 2. 非链表法,归纳推理
*/
public class 约瑟夫问题 {
public static int getResult(int n, int m) {
ArrayList<Integer> list = new ArrayList<>();
//首先进行编号
for (int i = 1; i <= n; i++) {
list.add(i);
}
int index = 0;
while (list.size() > 1) {
index = (index + m) % list.size();
Integer res = list.remove(index);
System.out.println(res);
index--;
}
return list.get(0);
}
/**
* 最终的递推关系式为
* f(1,m) = 0; (n=1)
* f(n,m)=(f(n-1,m)+m)%n; (n>1)
*/
/*
* 编号为(0~n-1)
* 用于返回幸存的节点
*/
public static int getResult1(int n, int m) {
if (n <= 0 || m <= 0) {
return -1;
}
int index = 0;
for (int i = 2; i <= n; ++i) {
index = (index + m) % i;
}
// 因为实际编号为(1~n)
return (index + 1);
}
public static void main(String[] args) {
System.out.println(getResult1(5, 2));
}
}
用单向循环链表实现:
import java.util.ArrayList;
public class 单向环形链表 {
class ListNode{
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
this.next = null;
}
}
int size = 0;
ListNode head = null;
ListNode tail = null;
public void add(int val){
ListNode node = new ListNode(val);
if(size == 0){
tail = node;
head = node;
node.next = node;
}else{
tail.next = node;
tail = tail.next;
node.next = head;
}
size++;
}
public void josephu(int n,int m){
if(n<=0 || m<=0){
System.out.println("不合法");
return;
}
ListNode pre = tail;
ListNode cur = head;
for (int i = 0; i < n; i++) {
for (int j = 1; j < m; j++) {
pre = pre.next;
cur = cur.next;
}
System.out.println(cur.val);
//删除当前节点
pre.next = cur.next;
//从后一个继续报数
cur = cur.next;
}
}
public void show(){
ArrayList<Integer> list = new ArrayList<>();
ListNode cur = head;
while(cur.next != head){
list.add(cur.val);
cur = cur.next;
}
list.add(tail.val);
System.out.println(list.toString());
}
public static void main(String[] args) {
单向环形链表 c = new 单向环形链表();
int n = 5;
int m = 2;
//构造
for (int i = 1; i <=n ; i++) {
c.add(i);
}
c.show();
c.josephu(n,m);
}
}
欢迎访问我的个人博客:http://www.ayjup.cn