【问题标题】:Find Survivor when n people are sitting in a circle当 n 个人围成一圈时找到幸存者
【发布时间】:2015-03-07 03:06:48
【问题描述】:

您好,我遇到了这个问题并试图解决这个问题

花点时间想象一下,你在一个房间里,房间里有 100 把椅子排成一圈。这些椅子按从一到一百的顺序编号。 在某个时间点,1 号椅子上的人会被告知离开房间。 2 号椅子上的人将被跳过,3 号椅子上的人将被告知离开。接下来是坐在#6 号椅子上的人。换句话说,最初会跳过 1 个人,然后是 2、3、4.. 等等。这种跳跃模式将继续围绕圆圈进行,直到只剩下一个人......幸存者。请注意,当人离开房间时,椅子会被移走。编写一个程序来确定幸存者坐在哪把椅子上。

我取得了不错的进展,但遇到了一个问题,计数达到 100 后,不知道如何从这里迭代,谁能帮助我,这是我的代码

import java.util.ArrayList;

public class FindSurvivor {

public static void main(String[] args) {
    System.out.println(getSurvivorNumber(10));
}

private static int getSurvivorNumber(int numChairs) {
    // Handle bad input
    if (numChairs < 1) {
        return -1;
    }

    // Populate chair array list
    ArrayList<Integer> chairs = new ArrayList<Integer>();
    for (int i = 0; i < numChairs; i++) {
        chairs.add(i + 1);
    }


    int chairIndex = 0;
    int lr =0;
    while (chairs.size() > 1) {
        chairs.remove(lr);
        chairIndex+=1;
        System.out.println(lr+" lr, size "+chairs.size()+" index "+chairIndex);
        if(lr==chairs.size()||lr==chairs.size()-1)
            lr=0;
        lr = lr+chairIndex;
        printChair(chairs);
        System.out.println();
    }

    return chairs.get(0);
}

public static void printChair(ArrayList<Integer> chairs){
    for(int i : chairs){
        System.out.print(i);
    }
}
}

【问题讨论】:

  • 那么在第二次迭代中,坐在1、4、7等椅子上的人(只计算剩下的椅子)会被踢出去?
  • 大概你想用类似lr = (lr + chairIndex) % chairs.size()的东西替换你当前的lr更新。
  • @TedHopp 是的,其余椅子上的人将根据计数变量被踢出..
  • 不存在这样的椅子。您已经拆除了每把椅子并将其用作武器。你是唯一的幸存者。

标签: java algorithm arraylist


【解决方案1】:

我不确定您的移除模式是什么,但我可能会将其实现为一个循环链表,其中第 100 个座位支架将连接回第一个座位支架。如果你使用数组,你将不得不担心每次移除后重新组织座位。

【讨论】:

  • 使用循环链表简单但效率不高(取O(mn),二次时间)。秩树解决方案在 O(n log n) 中求解。
  • @gknicker 这里 m=2(其他人都被淘汰了),所以这个建议给出了一个线性时间的解决方案。
【解决方案2】:

如果您的步骤是增量的,您可以使用以下代码:

    int cur = 0;
    int step = 1;
    while (chairs.size() > 1) {
        chairs.remove(cur);
        cur += ++step;
        cur %= chairs.size();
    }
    return chairs.get(0);

如果您的步骤固定为 1,那么根据 @Jarlax 提供的解释,您可以在 O(log n) 时间内用一行代码解决问题:

//for long values
public static long remaining(long numChairs) {
    return (numChairs << 1) - (long)Math.pow(2,Long.SIZE - Long.numberOfLeadingZeros(numChairs));
}

//for BigInteger values
public static BigInteger remaining(BigInteger numChairs) {
    return numChairs.shiftLeft(1).subtract(new BigInteger("2").pow(numChairs.bitLength()));
}

但是,如果您坚持使用 ArrayList,则您的代码不需要额外的变量。始终删除第一个元素并在列表末尾删除然后添加下一个元素。然而,这是 O(n)。

    while (chairs.size() > 1) {
        chairs.remove(0);
        chairs.add(chairs.remove(0));
    }
    return chairs.get(0);

【讨论】:

  • 感谢您提供解决方案,但它不是该问题的正确解决方案,因为在您的解决方案中只有一个跳过,但跳过应该按增量顺序排列,如 1,2,3,4 ...
  • 还添加了增量步骤的解决方案。 *虽然不清楚这是一个要求,这就是为什么我们所有人都根据固定的步骤回答。
【解决方案3】:

有优雅的解析解:

让我们改变人数:#2 -> #1, #3 -> #2, ..., #1 -> #100(最后我们只需要减去 1 来“修复”结果) .现在第一个人留下或离开。假设圈子里只有 64 人。很容易看出,在第一次淘汰后,圈子里会剩下 32 个人,编号将从 #1 重新开始。所以最后只剩下#1了。

我们有 100 人。在 36 人离开圈子后,我们最终将有 64 人 - 我们知道如何解决这个问题。对于每个离开房间的人,剩下一个人,所以 64 人的圈子将从 1 + 2*36 = #73(新 #1)开始。由于第一步的索引发生变化,最终答案将是 #72。

一般情况下 res = 2*(N - most_smaller_pow_2) = 2*N - most_larger_pow_2。代码很简单:

public static long remaining(long total) {
    long pow2 = 1;
    while (pow2 < total) {
        pow2 *= 2;
    }
    return 2*total - pow2;
}

此外,该算法的复杂度为 O(log(N)) 而不是 O(N),因此可以计算大量输入的函数(它可以很容易地适应使用 BigInteger 而不是 long)。

【讨论】:

  • 小评论。为了使代码完全符合描述:while循环中的条件应该是pow2 &lt;= total,在返回之前应该有if (result == 0) result += total。但是提供的版本是等效的,并且更简单一些。
  • 您好,感谢您的解决方案,但如果我们只跳过一个人,您的解决方案是有效的,但这里我们应该按递增顺序跳过人员..
【解决方案4】:

首先,让我们假设椅子从 0 开始编号。我们将在最后将编号切换回来 - 但通常情况下,从 0 而不是 1 枚举项目时事情会更简单。

现在,如果你有 n 个人并且你开始在 x 椅子上消除(x 是 0 或 1),那么在一次通过中你将消除一半的人。那么你有一个大约一半大小的问题(可能加一),如果你解决了这个问题,你可以通过将该子结果乘以 2 并可能加一来构造原始问题的解决方案。

要对此进行编码,只需将 4 种情况(n 奇数或偶数 vs x 0 或 1)正确。这是一个使用按位技巧正确处理 4 种情况的版本。

public static long j2(long n, long x) {
    if (n == 1) return 0;
    return j2(n/2 + (n&x), (n&1)^x) + 1-x;
}

现在可以编写从 1 开始编号的椅子且没有额外参数的解决方案:

public static long remaining(long n) {
    return 1 + j2(n, 0);
}

这在 O(log n) 时间内运行并使用 O(log n) 内存。

【讨论】:

    【解决方案5】:

    答案是 31。这里有三种不同的实现方式

    var lastSurvivor = function(skip, count, chairs) {
        //base case checks to see if there is a lone survivor
        if (chairs.length === 1)
            return chairs[0];
        //remove chairs when they are left/become dead
        chairs.splice(skip, 1);
        //increment the skip count so we know which chair
        //to leave next. 
        skip = (skip + 1 + count) % chairs.length;
        count++;
        //recursive call
        return lastSurvivor(skip, count, chairs);
    };
    
    /** TESTS *******************************************************************
    ----------------------------------------------------------------------------*/
    
    var result = lastSurvivor(0, 0, chairs);
    console.log('The lone survivor is located in chair #', result);
    // The lone survivor is located in chair # 31
    
    
    
    
    /** ALTERNATE IMPLEMENTATIONS ***********************************************
    -----------------------------------------------------------------------------
    
    /* Implemenation 2 
    -----------------*/
    
    var lastSurvivor2 = function(chairs, skip) {
        skip++;
        if (chairs === 1)
            return 1;
        else
            return ((lastSurvivor2(chairs - 1, skip) + skip - 1) % chairs) + 1;
    };
    
    /** Tests 2 *******************************************************************/
    
    var result = lastSurvivor2(100, 0);
    console.log('The lone survivor is located in chair #', result);
    // The lone survivor is located in chair # 31
    
    
    
    /* Implemenation 3 
    ------------------*/
    
    var chairs2 = [];
    for (var i = 1; i <= 100; i++)
        chairs2.push(i);
    
    var lastSurvivor3 = function(chairs, skip) {
        var count = 0;
        while (chairs.length > 1) {
            chairs.splice(skip, 1);
            skip = (skip + 1 + count) % chairs.length;
            count++;
        }
        return chairs[0];
    };
    
    /** Tests 3 *******************************************************************/
    
    var result = lastSurvivor3(chairs2, 0);
    console.log('The lone survivor is located in chair #', result);
    // The lone survivor is located in chair # 31
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      相关资源
      最近更新 更多