问题描述
N个人围成一圈,从第K个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
思路
- 本文章介绍使用单向环形链表解决该问题
- 创建指定节点个数单向环形列表
- 每次报数开始位置记为first节点以及前一节点Help,为了能每次找到并删除第M个节点
- 删除后再次刷新first节点,直到剩余一个节点
代码实现
/**
* 約瑟夫问题
*
* @author: ralap
* @date: created at 2019/6/7 17:40
*/
public class JosephuProblem {
public static void main(String[] args) {
JosephuProblem ysf = new JosephuProblem(50);
ysf.show();
ysf.solve(4, 8);
}
MyNode first;
private int count;
public JosephuProblem(int count) {
this.count = count;
if (count <= 0) {
throw new IllegalArgumentException("不支持该参数");
}
MyNode node;
MyNode temp = null;
for (int i = 1; i <= count; i++) {
node = new MyNode(i, "Ralap" + i);
if (temp == null) {
first = temp = node;
} else {
temp.next = node;
temp = node;
}
if (i == count) {
temp.next = first;
}
}
}
public void show() {
MyNode temp = first;
int showCount = count;
while (showCount > 0) {
System.out.println(temp);
temp = temp.next;
showCount--;
}
}
public void solve(int beginNum, int step) {
if (first == null || beginNum <= 0 || step <= 0) {
return;
}
MyNode help = getNode(((beginNum - 2 + count) % count) + 1);
first = help.next;
while (true) {
if (first.no == help.no) {
System.out.println("--->NO:" + first.no);
break;
} else {
for (int i = 1; i <= step; i++) {
first = first.next;
help = help.next;
}
System.out.println("--->NO:" + first.no);
first = first.next;
help.next = first;
}
}
}
//获取指定位小标节点
public MyNode getNode(int index) {
MyNode cur = null;
int getCount = 1;
while (getCount <= index) {
if (getCount == 1) {
cur = first;
} else {
cur = cur.next;
}
getCount++;
}
return cur;
}
}
class MyNode {
public int no;
public String name;
public MyNode next;
public MyNode(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "MyNode{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
网友评论