环形链表解决约瑟夫问题
约瑟夫问题
据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。
构思
我们可以采用环形链表解决约瑟夫问题。
环形链表构建思路:
约瑟夫问题实现思路:
代码实现
- 节点类
package com.linkedlist.circlesinglelinkedlist;
public class Node {
private int no;
private Node next;
public Node() {
}
public Node(int no) {
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
- 环形链表类
package com.linkedlist.circlesinglelinkedlist;
public class CircleSingleLinkedList {
private Node first = null;
public void addNode(int num){
if(num < 1){
System.out.println("添加节点数不能小于1!");
}
Node cur = null;
for (int i = 1; i <= num; i++) {
Node node = new Node(i);
if(i == 1){
first = node;
first.setNext(first);
cur = first;
}else{
cur.setNext(node);
node.setNext(first);
cur = cur.getNext();
}
}
}
public void list(){
if(first == null){
System.out.println("环形链表为null!");
return;
}
Node cur = first;
while(cur.getNext() != first){
System.out.println("编号:"+cur.getNo());
cur = cur.getNext();
}
System.out.println("编号:"+cur.getNo());
}
public void Josephus(int begin,int count,int num){
if(begin < 1 || count < 0 || begin > num){
System.out.println("参数不正确,请重新输入!");
return;
}
Node helper = first;
//让helper指向最后节点
while(helper.getNext() != first){
helper = helper.getNext();
}
//让helper和first遍历begin - 1
for (int i = 0; i < begin - 1; i++) {
helper = helper.getNext();
first = first.getNext();
}
//进行报数
while(true){
//只剩下一个节点
if(helper == first){
break;
}
for (int i = 0; i < count - 1; i++) {
helper = helper.getNext();
first = first.getNext();
}
System.out.println("编号:"+first.getNo()+"出圈!");
first = first.getNext();
helper.setNext(first);
}
System.out.println("存活编号:"+first.getNo());
}
}