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

我的解决方案如下:

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

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


当前回答

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[]中选择至少有多少你想为真:-)

其他回答

这个怎么样:

(a - b) ? c : a

这类问题可以用卡诺图来解决:

      | C | !C
------|---|----
 A  B | 1 | 1 
 A !B | 1 | 0
!A !B | 0 | 0
!A  B | 1 | 0

由此推断,第一行需要一组,第一列需要两组,得到聚基因润滑剂的最优解:

(C && (A || B)) || (A && B)  <---- first row
       ^
       |
   first column without third case
return 1 << $a << $b << $c >= 1 << 2;

三元运算符让人觉得很无聊,但它们也会令人困惑(使代码更难维护,从而增加了注入错误的可能性)。Jeff Attwood说得很好:

这是一个权衡取舍的完美例子 毫无意义的一次 写的时候节省了几十个 阅读时间理解惩罚——它 让我思考。

为了避免三元操作符,我创建了以下函数:

function atLeastTwoTrue($a, $b, $c) {
        $count = 0;

        if ($a) { $count++; }
        if ($b) { $count++; }
        if ($c) { $count++; }

        if ($count >= 2) {
                return true;
        } else {
                return false;
        }
}

这个和其他解一样酷吗?不。这样更容易理解吗?是的。这是否会使代码更具可维护性、bug更少?是的。

我不喜欢三元(return a ?(b || c):(b && c);从最上面的答案),我想我没有看到任何人提到过它。它是这样写的:

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