Use circular linked list to solve Josephus problem

Last updated on January 11, 2023 pm

[cited from wikipedia]Josephus Problem: A number of people are standing in a circle waiting to be executed. Counting begins at a specified point in the circle and proceeds around the circle in a specified direction. After a specified number of people are skipped, the next person is executed. The procedure is repeated with the remaining people, starting with the next person, going in the same direction and skipping the same number of people, until only one person remains, and is freed.

The problem—given the number of people, starting point, direction, and number to be skipped—is to choose the position in the initial circle to avoid execution.

Nodes in the list(data + next)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Node {
private int no;
private Node next;

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;
}
}

Circular linked list and the solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class CircleSinglyLinkedList {
//initiate the first point
private Node first = new Node(-1);

//add nodes to the list
public void addNode(int nums) {
if (nums < 1) {
System.out.println("nums should not be smaller than 1.");
return;
}

Node curNode = null;
for (int i = 1; i <= nums; i++) {
Node child = new Node(i);
if (i == 1) {
first = child;
first.setNext(first);
curNode = first;
} else {
curNode.setNext(child);
curNode = child;
child.setNext(first);
}
}
}

//iterate the list
public void showList() {
//whether the list is empty
if (first == null) {
System.out.println("This list is empty.");
return;
}

Node curNode = first;
while (true) {
System.out.println("The number of node is " + curNode.getNo());
if (curNode.getNext() == first) {
break;
} else {
curNode = curNode.getNext();
}
}
}

/**
* solve Josephus problem by Circle Single Linked List
* 1、创建helper指针,开始时指向环形链表最后一个结点
* 2、开始count时,count m次即将first和helper同时移动m-1次
* 3、然后将数到的结点出列
*
* @param startNo start from it
* @param countNum every 'countNum' get one node
* @param sum original number of nodes
*/
public void josephus(int startNo, int countNum, int sum) {
if (first == null || startNo < 1 ||startNo>sum){
System.out.println("There's something wrong with the list or the augments.");
return;
}

//create a helper and point it to the last node
Node helper = first;
while (true){
if (helper.getNext() == first){
break;
}
helper = helper.getNext();
}

//move first and helper point to the startNo
for (int i = 0; i < startNo -1; i++){
first = first.getNext();
helper = helper.getNext();
}

//start the count process
while (true){
//only one node left in the list
if (helper == first){
break;
}

for (int i = 0; i <countNum-1; i++){
first = first.getNext();
helper = helper.getNext();
}

//get the 'first' node
System.out.println("Get the '" + first.getNo() +"' node");
first = first.getNext();
helper.setNext(first);
}
System.out.println("The last node is " + first.getNo());
}
}

test

1
2
3
4
5
6
7
8
public static void main(String[] args) {
CircleSinglyLinkedList circleSinglyLinkedList = new CircleSinglyLinkedList();
circleSinglyLinkedList.addNode(5);
circleSinglyLinkedList.showList();

//test the Josephus
circleSinglyLinkedList.josephus(1,2,5);
}

Use circular linked list to solve Josephus problem
http://hihiko.zxy/2023/01/11/Use-circular-linked-list-to-solve-Josephus-problem/
Author
Posted on
January 11, 2023
Licensed under