问题描述
- List item
从1开始数,数到3枪毙,从下一个继续开始数,直到最后剩一个
解题思路(用双向循环链表进行解决,单向循环链表也一样)
- a.定义数据结构,增加一个数据成员current:用于指向某个结点
- b.增加三个方法
1.void reset():让current指向头结点first
2.E next():让current往后走一步,也就是current = current.next
3.E remove():删除current指向的结点,删除成功后让current指向下一个结点
1.数据结构
public class CircleLinkedList<E> extends AbstractList<E> {
private Node<E> first;
private Node<E> last;
private Node<E> current;
private static class Node<E> {
E element;
Node<E> prev;
Node<E> next;
public Node(Node<E> prev, E element, Node<E> next) {
this.prev = prev;
this.element = element;
this.next = next;
}
}
}
2.添加方法
public void reset() {
current = first;
}
public E next() {
if (current == null) return null;
current = current.next;
return current.element;
}
public E remove() {
if (current == null) return null;
Node<E> next = current.next; //获取当前结点的下一个
E element = remove(current);//删除当前结点 调用下面的方法
if (size == 0) {
current = null;
} else {
current = next;
}
return element;
}
private E remove(Node<E> node) {
if (size == 1) {
first = null;
last = null;
} else {
Node<E> prev = node.prev;
Node<E> next = node.next;
prev.next = next;
next.prev = prev;
if (node == first) { // index == 0
first = next;
}
if (node == last) { // index == size - 1
last = prev;
}
}
size--;
return node.element;
}
3.算法描述
static void josephus() {
CircleLinkedList<Integer> list = new CircleLinkedList<>();
for (int i = 1; i <= 8; i++) {
list.add(i);
}
// 指向头结点(指向1)
list.reset();
while (!list.isEmpty()) {
// 数1 2 3即next两次后删除当时的current元素结点
list.next();
list.next();
System.out.println(list.remove());
}
}