一位面试官最近问了我这样一个问题:给定三个布尔变量a、b和c,如果三个变量中至少有两个为真,则返回true。

我的解决方案如下:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    else{
        return false;
    }
}

他说这还可以进一步改进,但如何改进呢?


当前回答

在c#中,我首先想到的是:

public bool lol(int minTrue, params bool[] bools)
{
    return bools.Count( ( b ) => b ) >= minTrue;
}

应该很快。

调用应该是这样的:

lol( 2, true, true, false );

这样,您就将规则(两个必须为真)留给调用者,而不是将它们嵌入到方法中。

其他回答

One thing I haven't seen others point out is that a standard thing to do in the "please write me some code" section of the job interview is to say "Could you improve that?" or "Are you completely happy with that" or "is that as optimized as possible?" when you say you are done. It's possible you heard "how would you improve that" as "this might be improved; how?". In this case changing the if(x) return true; else return false; idiom to just return x is an improvement - but be aware that there are times they just want to see how you react to the question. I have heard that some interviewers will insist there is a flaw in perfect code just to see how you cope with it.

这样读起来更好:

if (a) {
    return b || c;
} 
else {
    return b && c;
}

这真的取决于你对“改进”的定义:

清晰吗?

boolean twoOrMoreAreTrue(boolean a, boolean b, boolean c)
{
    return (a && b) || (a && c) || (b && c);
}

反之亦然?

boolean moreThanTwo(boolean a, boolean b, boolean c)
{
    return a == b ? a : c;
}

更一般的?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(boolean b : bs)
    {
        count += b ? 1 : 0;

        if(count > x) return true;
    }

    return false;
}

更多的可伸缩的吗?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(int i < 0; i < bs.length; i++)
    {
        count += bs[i] ? 1 : 0;

        if(count > x) return true;

        int needed = x - count;
        int remaining = bs.length - i;

        if(needed >= remaining) return false;
    }

    return false;
}

更快呢?

// Only profiling can answer this.

哪一种是“改进”的,很大程度上取决于具体情况。

作为@TofuBeer TofuBeer精彩帖子的补充,考虑@pdox pdox的回答:

static boolean five(final boolean a, final boolean b, final boolean c)
{
    return a == b ? a : c;
}

再考虑一下它的分解版本,如"javap -c"所给出的:

static boolean five(boolean, boolean, boolean);
  Code:
    0:    iload_0
    1:    iload_1
    2:    if_icmpne    9
    5:    iload_0
    6:    goto    10
    9:    iload_2
   10:    ireturn

Pdox的答案编译成的字节代码比之前的任何答案都要少。它的执行时间与其他的相比如何?

one                5242 ms
two                6318 ms
three (moonshadow) 3806 ms
four               7192 ms
five  (pdox)       3650 ms

至少在我的电脑上,pdox的回答比@moonshadow moonshadow的回答稍微快一点,使得pdox的回答是最快的(在我的惠普/英特尔笔记本电脑上)。

public static boolean atLeast(int atLeastToBeTrue, boolean...bools){
    int booleansTrue = 0;
    for(boolean tmp : bools){
        booleansTrue += tmp ? 1 : 0;
    }
    return booleansTrue >= atLeastToBeTrue;
}

你可以从varargs a.k.a boolean[]中选择至少有多少你想为真:-)