[题目大意]: 约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
[输入]: 每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是: 0 0
[输出]: 对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号 样例输入
6 2
12 4
8 3
0 0
样例输出
5
1
7 解题步骤:
1、首先是定义节点,每个猴子有一个编号和下一个猴子的信息
1 class Node<T> {
2
3 T data;
4 Node next;
5
6 public Node(T data, Node<T> next) {
7 this.data = data;
8 this.next = next;
9 }
10
11 public Node getNext() {
12 return next;
13 }
14
15 public void setNext(Node next) {
16 this.next = next;
17 }
18
19 public T getData() {
20 return data;
21 }
22
23 public void setData(T data) {
24 this.data = data;
25 }
26 }
2
3 T data;
4 Node next;
5
6 public Node(T data, Node<T> next) {
7 this.data = data;
8 this.next = next;
9 }
10
11 public Node getNext() {
12 return next;
13 }
14
15 public void setNext(Node next) {
16 this.next = next;
17 }
18
19 public T getData() {
20 return data;
21 }
22
23 public void setData(T data) {
24 this.data = data;
25 }
26 }
2、建立循环链表
public void add(T data) {
if (size == 0) {
head = new Node<T>(data, null);
tail = head;
current = head;
} else {
tail.next = new Node<T>(data, head);
tail = tail.next;
}
size++;
}
3、猴子数到n时,就退出循环链表中
public T remove(boolean flag) {
if (flag) {
if (current.next == head) {
head = current.next.next;
} else if (current.next == tail) {
tail = current;
}
current.next = current.next.next;
size--;
return current.getData();
} else {
current = current.next;
return current.getData();
}
}
最后就是在主函数中测试:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while (true) {
int k = 1;// 用于计数,
int m = s.nextInt();// 表示数到m时m退出
int n = s.nextInt();// 表示公有多少人
if (m == 0 && n == 0)
break;
Josephus<Integer> l = new Josephus<Integer>();
for (int i = 0; i < n; i++) {
l.add(i);
}
while (true) {
if (k % m != 0) {
l.remove(false);
k++;
} else {
l.remove(true);
k = 1;// 如果人数是k的整数倍,则k的值为1
}
if (l.getSize() == 1) {
System.out.println(l.current.getData());
break;
}
}
}
下面是全部的代码:
View Code