この実行シーケンスを出力するという質問に答えるには、シミュレーションが必要です。これは、O(nk) の複雑さを意味します。同時に O(nlogn) 時間の複雑さを求めながら、[O(n) である] 実行シーケンスを取得することは不可能です。処刑されるすべての人を出力する必要があるため、O(n) です。
kkonrad の Range Trees への言及は、優れた O(nlogn) ソリューションをもたらします。他の人が指摘しているように、循環リンクリストはこの問題の効率的なデータ構造です。Code Review の 200_success の Java ソリューションは、非常に洗練されていて読みやすいと思います。
public class CircularGunmenIterator<T> implements Iterator<T> {
private List<T> list;
private Iterator<T> iter;
public CircularGunmenIterator(List<T> list) {
this.list = list;
this.iter = list.iterator();
}
@Override
public boolean hasNext() {
// Continue as long as there is a shooter and a victim
return this.list.size() >= 2;
}
@Override
public T next() {
if (!this.iter.hasNext()) {
// Wrap around, creating the illusion of a circular buffer
this.iter = this.list.iterator();
}
return this.iter.next();
}
@Override
public void remove() {
this.iter.remove();
}
public static void main(String[] args) {
// Create the gunmen
List<Integer> gunmen = new LinkedList<Integer>();
for (int i = 1; i <= 100; i++) {
gunmen.add(i);
}
// Shootout!
Iterator<Integer> ringIter = new CircularGunmenIterator<Integer>(gunmen);
while (ringIter.hasNext()) {
Integer shooter = ringIter.next();
Integer victim = ringIter.next();
System.out.printf("%2d shoots %2d\n", shooter, victim);
ringIter.remove(); // Bang!
}
System.out.println("Last one alive: " + gunmen.get(0));
}
}
このヨセフスの問題 (k = 2) については、ウィキペディアに詳細がいくつかあります。
http://en.wikipedia.org/wiki/Josephus_problem