100人围成一个圈,手里拿着枪。 1杀死2、3杀死4、5杀死6,依此类推,直到我们只剩下一个人。谁将是最后一个活着的人。编写代码以有效地实现此目标。
这是我的Java实现:
public static void main(String[] args) throws Exception {
int numberOfGuys = 100;
MyObject[] objetList = new MyObject[numberOfGuys];
for(int i=1;i<numberOfGuys+1;i++) {
objetList[i-1] = new MyObject(i);
}
boolean oneElementLeft = false;
while(!oneElementLeft) {
for(int i=0;i<objetList.length;i++) {
if(i != objetList.length-1 && (i+1)%2==1) {
objetList[i+1]=null;
}
if(i == objetList.length-1 && objetList[i] != null) {
objetList[0]=null;
}
}
List<MyObject> newList = new ArrayList<MyObject>();
for (MyObject myObject:objetList) {
if(myObject != null) {
newList.add(myObject);
}
}
objetList = new MyObject[newList.size()];
for(int i=0;i<newList.size();i++) {
objetList[i] = newList.get(i);
}
if(objetList.length==1) {
oneElementLeft = true;
}
}
System.out.println(objetList[0].getIndex());
}
我不是数学家,所以我不太了解使用公式,递归等的巧妙解决方案...
欢迎任何评论或带有解释的更好代码。
#1 楼
链接问题中可接受的答案使用了一个循环链接列表,它是最能代表这种情况的数据结构。该答案说明了如何执行该实现,因此,我将重点放在您要采用的方法上,如果该方法可以产生等效的结果,则同样有效。public static void main(String[] args) throws Exception {
为什么您的
main
方法会抛出Exception
?这是无用的,并且可能造成混淆。您的代码没有遇到任何预期的异常,那么为什么要告诉读者一个例外呢?您告诉他们的异常是任何异常,它本身完全没有帮助。如果您的程序遇到未捕获的异常,它将以相同的方式死亡。放下throws Exception
。int numberOfGuys = 100;
这很好,但是很多人可能会将其移出方法
static final int NUMBER_OF_GUYS = 100;
,因为它本质上是一个常数(除非您计划在程序的另一次迭代中根据输入来更改它)。MyObject[] objetList = new MyObject[numberOfGuys];
这里有两个主要问题。首先是命名。
MyObject
是一个可怕的名字,它没有告诉读者此类的本质。一个更好的名字可能是Gunman
或Shooter
等。对于变量名,objetList
也是一个糟糕的名字。首先,它看起来非常接近objectList,这增加了拼写错误的可能性。它也几乎没有说明变量的性质,并且它所说的是错误的。后缀“列表”可能被解释为表示这是一个List
对象,但不是。更好的名称可能是gunmen
或shooters
(最好从其持有的对象的类名匹配)。第二个主要问题是选择的数据结构。我们知道将要从此结构中删除元素,但是我们也知道这对于原始数组是无效的。要么通过使用null进行删除,而必须在循环中检查该条件,要么通过每次删除元素时通过复制数组来进行删除,但不添加元素。为这种情况构建的数据结构是
List
。有多种选择,每种都有可能提供不同的性能配置文件,但是如果不满足性能要求,我们可以选择一个启动并进行更改。for(int i=1;i<numberOfGuys+1;i++) {
objetList[i-1] = new MyObject(i);
}
首先,间距很重要。读取在运算符等之间没有空格的代码要困难得多。其次,您执行过多的操作,使循环的工作变得混乱。而不是从1开始,转到
numberOfGuys + 1
,然后从索引0插入索引objetList[i-1]
,它看起来像这样:for(int i = 0; i < numberOfGuys; i++) {
objetList[i] = new MyObject(i + 1);
}
boolean oneElementLeft = false;
while(!oneElementLeft) {
...
if(objetList.length==1) {
oneElementLeft = true;
}
}
(SPOILER:在更改代码之前,请通读本部分。)
该代码讲述了一个故事,但其中充满了噪音。我们针对布尔进行测试,如果布尔发生变化,则退出循环。我们将仅基于在循环结束时检查的布尔测试(
objetList.length == 1
)来更改该布尔。我们已经有了一个更简洁地执行此操作的循环结构:do-while循环!我们可以重写它,以便我们只有do { ... } while(objetList.length != 1);
这么干净!错了该代码讲述的故事具有误导性,并且实际上是越野车。如果objetList.length
已经为1,我们什么都不想做!我们想要的是一个简单的while循环,不需要标志:while(objetList.length > 1) {
...
}
for(int i=0;i<objetList.length;i++) {
if(i != objetList.length-1 && (i+1)%2==1) {
objetList[i+1]=null;
}
if(i == objetList.length-1 && objetList[i] != null) {
objetList[0]=null;
}
}
再次,间隔。
这些条件并不能真正说明一个清晰的故事。首先要注意的是,
(i+1)%2 == 1
询问i
加一是否为奇数。但是,真正要问的是i
是偶数还是更简洁地是i % 2 == 0
。 (您有时还会看到此内容写为i & 1 == 0
)。不过,从更一般的角度看,我们将使奇数元素无效,如果列表为奇数长度,则将第一个元素为零。但是,条件句不会出来并说清楚。我们检查每次迭代是否都在列表的末尾,并且仅在某些特殊条件下才到达末尾。也不完全清楚条件是否是列表为奇数长度。更清楚地说,我们可以这样写:for(int i = 0; i < objetList.length - 1; i += 2) {
objetList[i + 1] = null;
}
if(objetList.length % 2 == 1) {
objetList[0] = null;
}
还要注意这里使用的垂直间距。我们经常需要在两个方向上都留有空间,以使代码更具可读性。
List<MyObject> newList = new ArrayList<MyObject>();
for (MyObject myObject:objetList) {
if(myObject != null) {
newList.add(myObject);
}
}
objetList = new MyObject[newList.size()];
for(int i=0;i<newList.size();i++) {
objetList[i] = newList.get(i);
}
这里的代码基本上只是混洗数组数据。这是最大的指示,表明原始数组是要使用的错误数据结构。
我编写了以下版本,该版本以类似(非循环)的方式完成相同的操作。可以通过在其中使用迭代器来改进它,但是它本身就足够了。
主类:
public class Main
{
public static final int NUMBER_OF_GUNMEN = 100;
public static void main(String[] args) {
List<Gunman> gunmen = new ArrayList<>(NUMBER_OF_GUNMEN);
for(int i = 1; i <= NUMBER_OF_GUNMEN; i++) {
gunmen.add(new Gunman(i));
}
while(gunmen.size() > 1) {
for(int i = 0; i < gunmen.size(); i++) {
Gunman killer = gunmen.get(i);
Gunman killed = gunmen.remove((i + 1) % gunmen.size());
System.out.println(killer.getNumber() + " kills " + killed.getNumber());
}
}
System.out.println("\n" + gunmen.get(0).getNumber() + " lives another day...");
}
}
Gunman类:
public class Gunman
{
private int number;
public Gunman(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
评论
\ $ \ begingroup \ $
非常感谢。您大部分(如果不是全部)评论都正确。 Oracle还建议使用约定:for(初始化;条件;更新){语句; },因此我将根据此模板进行修复!
\ $ \ endgroup \ $
–科雷·图吉(Koray Tugay)
2014年7月14日5:18
\ $ \ begingroup \ $
代码很简单,很好。但是,该问题要求高效的代码,并且ArrayList.remove()效率不高。第一枪杀死2号,导致复制了98个元素。
\ $ \ endgroup \ $
– 200_success
14年7月14日在5:38
\ $ \ begingroup \ $
@ 200_success你是对的。我的代码试图反映他的方法。我从三个方面谈谈绩效。首先,我注意到循环链表是最正确使用的结构。稍后,我注意到我们可以根据性能标准通过多态性来改变使用的列表结构。最后,我注意到可以使用迭代器来改进我的实现。总之,使用ArrayList或LinkedList,对我来说100个元素在〜0.1s内完成。这样做的效率是,我现在编写工作代码,而不是花20分钟研究Java列表来优化毫秒。
\ $ \ endgroup \ $
–cbojar
2014年7月14日15:11
\ $ \ begingroup \ $
很公平。我认为它是一个非常彻底的答案。
\ $ \ endgroup \ $
– 200_success
14年7月14日在15:14
\ $ \ begingroup \ $
虽然您的回答是正确和良好的(为此投票),但我确实有两个小问题:首先是您的持枪者名单。它包含100名枪手,因此至少必须是多名枪手。其次,在OO中,除了构建测试用例之外,我不喜欢看到静态void主逻辑。您的前四行是正确的(也许可以是方法中的),但是您的最后一行应类似于System.out.println(“ \ n” + GunMenShotDown.whoStands(players).getNumber()+“生活在另一天。 ..”)。 (在工作面试中做测试用例时非常重要)
\ $ \ endgroup \ $
– chillworld
2014年7月29日5:15
#2 楼
有时数学可能会令人困惑,有时可能会有所帮助,但是使用一些数学方法,解决此问题的方法是:public static final int getSurvivingGunman(int startCount) {
return 1 + (startCount - Integer.highestOneBit(startCount)) * 2;
}
您的主要方法如下所示:
public static void main (String[] args) {
System.out.println(getSurvivingGunman(100));
}
哪个产生:
73
现在,关于它为什么起作用,请考虑问题:
如果正好有2名枪手,那么幸存者就是1名。
如果正好有4名枪手,那么在第一回合之后,就有2名枪手,还有1名幸存者。
如果枪手的人数是2的精确乘方,那么幸存者就是枪手1。
这很容易,但是其他大小的人....
2的所有幂都是偶数(20之后),因此,如果添加一个枪手,则第一个“回合”将是奇数,最后一个枪手将射击第一个枪手,这意味着下一轮将从枪手2开始,实际上跳过了两个。
本质上讲,对于每位持枪人,在获得2的幂之前,幸存的持枪者将领先2位。
Java m希望通过
Integer.highestOneBit(int)
函数轻松找到2的前次幂,而其余函数很容易。如果使用以下主要方法运行它:
public static void main(String[] args) {
for (int start = 0; start <= 100; start++) {
System.out.printf("%3d gunmen has %3d survivor%n", start, getSurvivingGunman(start));
}
}
模式更加明显。
此外,由于算法的时间复杂度为\ $ O(1)\ $,因此您可以执行以下操作:
for (int start = 10; start <= 1000000000; start *= 10) {
System.out.printf("%3d gunmen has %3d survivor%n", start, getSurvivingGunman(start));
}
并快速获得结果:
10 gunmen has 5 survivor
100 gunmen has 73 survivor
1000 gunmen has 977 survivor
10000 gunmen has 3617 survivor
100000 gunmen has 68929 survivor
1000000 gunmen has 951425 survivor
10000000 gunmen has 3222785 survivor
100000000 gunmen has 65782273 survivor
1000000000 gunmen has 926258177 survivor
#3 楼
批判我认为暗含了以下代码:
public class MyObject {
private int index;
public MyObject(int i) {
this.index = i;
}
public int getIndex() {
return index;
}
public static void main(String[] args) {
…
}
}
可以,但是
MyObject
是一个类中信息最少的名称。 Gunman
会更好。同样,我建议将objetList
重命名为gunmen
。oneElementList
变量是没有意义的。您可以说while (objetList.length != 1) { … }
到达终点后重新合并列表效率很低。您想要实现一个循环列表,或者像我在下面所做的那样,通过使用迭代器来模拟一个循环缓冲区。由于该问题要求频繁拼接元素,因此这是在少数情况下使用链表的情况之一。
建议的解决方案
枪战循环可能会变得相当复杂,值得对其进行简化。通过使用迭代器,我们可以完全不必使用任何数组索引。
在这个问题上,枪手只是个数字。我用
Integer
表示它。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));
}
}
评论
\ $ \ begingroup \ $
很好的解决方案,非常感谢。也很清楚。
\ $ \ endgroup \ $
–科雷·图吉(Koray Tugay)
14年7月14日在5:20
#4 楼
我尝试通过递归解决此问题:package com.study.recursion;
import java.util.List;
public class GunMens {
private static final int SECOND_ELEMENT = 1;
private static final int FIRST_ELEMENT = 0;
public Integer killingStartsFrom(int gunManWhokillsNextPerson,List<Integer> groupOfGunMens) throws Exception{
if(groupOfGunMens.size() ==0){
throw new Exception("No GunMen is present .. Cannot continue Killing :)");
}
if(groupOfGunMens.size()==1){
return groupOfGunMens.get(FIRST_ELEMENT);
}
else if(groupOfGunMens.size() ==2){
if(gunManWhokillsNextPerson==SECOND_ELEMENT){
return groupOfGunMens.get(SECOND_ELEMENT);
}else {
return groupOfGunMens.get(FIRST_ELEMENT);
}
}
else if(gunManWhokillsNextPerson == groupOfGunMens.size()-1){
groupOfGunMens.remove(FIRST_ELEMENT);
return killingStartsFrom(FIRST_ELEMENT,groupOfGunMens);
}
else if(gunManWhokillsNextPerson+1 == groupOfGunMens.size()-1){
groupOfGunMens.remove(gunManWhokillsNextPerson+1);
return killingStartsFrom(FIRST_ELEMENT,groupOfGunMens);
}
else{
groupOfGunMens.remove(gunManWhokillsNextPerson+1);
return killingStartsFrom(gunManWhokillsNextPerson+1,groupOfGunMens);
}
}
}
该程序的好处:
这将为您带来相同的效果
该程序还提供了指定谁应该开始射击的方法(即,射击可能从第三人称开始,幸存者在这种情况下会有所不同)。
该程序涉及的场景:
如果不存在口香糖,则程序会说“无法继续杀死:)”(请注意结尾处的笑脸)。
如果如果只有两名枪手在场,那么他就是幸存者。
如果有两名枪手在场,则只有两种情况需要测试,任何开始射击的人都是幸存者。
每个呼叫/递归中都有多个枪手。枪手会杀死下一个人,直到只剩下两个枪手为止。
杀人可以从任何枪手处开始,例如每100名枪手中就有四名可以开始射击。
我编写了以下测试类,其中编写了Junit来测试行为:
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.study.recursion.GunMens;
public class GunMensTest {
GunMens mens = new GunMens();
@Test(expected =Exception.class)
public final void test_NoGunMen_ShouldThrowException() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(gunMenSurvived,new Integer(0));
}
@Test
public final void test_OneGunMen_HeShouldBeTheSurvivor() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(1),gunMenSurvived);
}
@Test
public final void test_TwoGunMen_OneWhoStarts_isTheSurvivor() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(1),gunMenSurvived);
}
@Test
public final void test_TwoGunMen_OneWhoStarts_isTheSurvivor_2() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);
Integer gunMenSurvived = mens.killingStartsFrom(1, gunmens);
assertEquals(new Integer(2),gunMenSurvived);
}
@Test
public final void test_FourGunMen_ShootingStartsWithFirstPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(1),gunMenSurvived);
}
@Test
public final void test_FourGunMen_ShootingStartsWithSecondPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);
Integer gunMenSurvived = mens.killingStartsFrom(1, gunmens);
assertEquals(new Integer(2),gunMenSurvived);
}
@Test
public final void test_FourGunMen_ShootingStartsWithThirdPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);
Integer gunMenSurvived = mens.killingStartsFrom(2, gunmens);
assertEquals(new Integer(3),gunMenSurvived);
}
@Test
public final void test_FourGunMen_ShootingStartsWithFourthPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);
Integer gunMenSurvived = mens.killingStartsFrom(3, gunmens);
assertEquals(new Integer(4),gunMenSurvived);
}
@Test
public final void test_FiveGunMen_ShootingStartsWithFirstPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);gunmens.add(5);
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(3),gunMenSurvived);
}
@Test
public final void test_FiveGunMen_ShootingStartsWithThirdPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);gunmens.add(5);
Integer gunMenSurvived = mens.killingStartsFrom(2, gunmens);
assertEquals(new Integer(5),gunMenSurvived);
}
@Test
public final void test_FiveGunMen_ShootingStartsWithFifthPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);gunmens.add(5);
Integer gunMenSurvived = mens.killingStartsFrom(4, gunmens);
assertEquals(new Integer(2),gunMenSurvived);
}
@Test
public final void test_SixGunMen_ShootingStartsWithFifthPerson() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
gunmens.add(1);gunmens.add(2);gunmens.add(3);gunmens.add(4);gunmens.add(5);gunmens.add(6);
Integer gunMenSurvived = mens.killingStartsFrom(4, gunmens);
assertEquals(new Integer(3),gunMenSurvived);
}
@Test
public final void test_HundredGunMen_killingStartsFromFirst() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
for(int i =0; i<100;i++){
gunmens.add(i+1);
}
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(73),gunMenSurvived);
}
@Test
public final void test_HundredGunMen_killingStartsFromSecond() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
for(int i =0; i<100;i++){
gunmens.add(i+1);
}
Integer gunMenSurvived = mens.killingStartsFrom(1, gunmens);
assertEquals(new Integer(74),gunMenSurvived);
}
@Test
public final void test_HundredGunMen_killingStartsFromTenth() throws Exception {
List<Integer> gunmens = new ArrayList<Integer>();
for(int i =0; i<100;i++){
gunmens.add(i+1);
}
Integer gunMenSurvived = mens.killingStartsFrom(9, gunmens);
assertEquals(new Integer(82),gunMenSurvived);
}
@Test
public final void test_ThousandGunMen_killingStartsFromFirst() throws Exception {
List<Integer> gunmens = new LinkedList<Integer>();
for(int i =0; i<1000;i++){
gunmens.add(i+1);
}
Integer gunMenSurvived = mens.killingStartsFrom(0, gunmens);
assertEquals(new Integer(977),gunMenSurvived);
}
}
范围改进:
如果与10000名持枪手尝试,此程序将引发堆栈溢出异常。但是我相信问题陈述是100名持枪者,因此该解决方案将达到目的。
评论
\ $ \ begingroup \ $
您的if-elseif语句可能会有所改进,但是在答案中加入了单元测试真是太棒了!
\ $ \ endgroup \ $
– Pimgd
14年7月29日在13:15
#5 楼
@cbojar和@ 200_success的代码解决方案都非常适合此问题。正如其他人指出的那样,链表迭代器绝对可以更有效地解决此问题。作为次要说明,在@cbojar的最终解决方案中,它在
ArrayList
初始化中缺少Gunman。List<Gunman> gunmen = new ArrayList<>(NUMBER_OF_GUNMEN);
如果您感兴趣:数学上,这是k = 2的约瑟夫斯问题。它已通过归纳证明,详细信息可在此处找到。
评论
\ $ \ begingroup \ $
从Java 7开始,我们有了菱形运算符,这意味着我们在初始化中不再需要显式引用Gunman。如果这是<= Java 6,那将是正确的。
\ $ \ endgroup \ $
–cbojar
2014年7月28日,下午3:28
#6 楼
这是约瑟夫斯问题的特例:有些人围成一圈等待执行。
计数开始于圆的某个点,并沿固定的方向围绕圆进行。在每个步骤中,将跳过一定数量的
人员,然后执行下一个人员。消灭
绕圈行进(随着被处决的人被撤职,这个圈子越来越小),直到只有最后一个剩下的人被赋予自由。我们的任务是在最初的
圈子中选择位置,以便您成为最后一个幸存者,从而生存下来。
问题中描述的100个枪手场景等同于
josephus(100, 2, 1)
。要获取整个序列,请使用import java.util.*;
public static void main(String[] argv)
{
System.out.println(josephus(100,2,1));
}
最后一个人站在
josephus(100,2,1).get(99)
的位置。步骤== 2时最有效的是解析解决方案(请参见@rolfl的答案),运行时间为
O(1)
。如果步进参数从2变为3或更大,运行时间将增加为
O(N)
。// remove N elements in equal steps starting at specific point
static List<Integer> josephus(int N, int step, int start)
{
if (N < 1 || step < 1 || start < 1) return null;
List<Integer> p = new LinkedList<Integer>();
for (int i = 0; i < N; i++)
p.add(i+1);
List<Integer> r = new LinkedList<Integer>();
int i = (start - 2) % N;
for (int j = N; j > 0; j--) {
i = (i + step) % N--;
r.add(p.remove(i--));
}
return r;
}
#7 楼
一种替代方法是使用Java 8引入的方法,用于处理数据的removeIf
和用于创建要处理的数据的Stream API。 import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
// 100 people are standing in a circle with gun in their hands.
// 1 kills 2, 3 kills 4, 5 kills 6 and so on till we are left with only one person.
// Who will be the last person alive. Write code to implement this efficiently.
public class Gunmen {
public static void main(String[] args) {
List<Integer> gunmen = IntStream.iterate(1, i -> i + 1).limit(100).boxed().collect(Collectors.toList());
while (gunmen.size() != 1) {
// If there are odd number of gunmen, the last will kill the first
final boolean willLastGunmanKillFirst = gunmen.size() % 2 != 0;
// Start killing from 1.. All gunman that reside in even indices will be removed..
gunmen.removeIf(integer -> gunmen.indexOf(integer) % 2 != 0);
// Kill the first if needed
if (willLastGunmanKillFirst) {
gunmen.remove(0);
}
}
System.out.println(gunmen); // [73]
}
}
评论
请重新考虑您的q。从头开始。 100被99杀死。谁杀死99? 98.谁杀死了98?如果从1开始杀死2,谁杀死3?你这样说,1杀死所有人:-P,或者你是什么意思?用铅笔和纸画。@Thufir为简单起见,考虑5个人:1杀死2,(2死了),3杀死4,(4死了),5杀死1,(1死了,2死了),3杀死5(4是已经死了),赢得了3场胜利。
嗯,很好。我认为这个问题被误解了。就答案而言,我认为至少有必要使用链接列表,或者更容易使用链接列表。
@Thufir我认为尝试向后退不会解决地球上的每个问题。 :)您能否提供LinkedList解决方案?我认为这样会更清洁一点,您是对的,但是它的工作原理非常相似,对吧?
链接的SO问题已被删除.....链接腐烂。这就是为什么在“代码审查”中我们坚持使用未链接的代码。