检查三个布尔值中至少有两个为真

612

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

我的解决方案如下:

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

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


173
将返回语句内联。 - Finglas
82
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou) - Andrew Grimm
6
Thorbjørn 问道:C语言中是否使用0/非0来表示布尔值?我认为这种情况在C语言中不适用,例如atLeastTwo(0,2,0)。请问您的看法? - Ken
93
为什么人们会给那些最琐碎的问题点赞? - BlueRaja - Danny Pflughoeft
52
通俗易懂的问题会得到很多赞,而过于具体和技术性的问题则不会。 - Jay
显示剩余14条评论
65个回答

3
这样读起来更好一些:

这种阅读体验更佳:

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

3
当我看到这个问题时,我的第一个想法是:
int count=0;
if (a)
    ++count;
if (b)
    ++count;
if (c)
    ++count;
return count>=2;

看到其他帖子后,我承认

return (a?1:0)+(b?1:0)+(c?1:0)>=2;

这种方法更加优雅。我想知道相对运行时间是多少。

无论如何,我认为这种解决方案要比其他解决方案好得多。

return a&b | b&c | a&c;

使用变量的数量可以更容易地扩展。如果以后我们添加了第四个必须测试的变量怎么办?如果变量的数量在运行时确定,并且我们传递了一个大小未知的布尔数组怎么办?依赖计数的解决方案比依赖列出每种可能组合的解决方案更容易扩展。此外,当列出所有可能的组合时,我怀疑很容易犯错误。试着编写“任意 4 个中的 3 个”的代码,并确保您没有漏掉任何一个也没有重复。现在尝试一下“任意 7 个中的 5 个”。


你可以更进一步:我相信在C语言中,你可以这样做:return a+b+c>1; - Joan Rieu
Fififox:没错,但问题标记为“Java”,这种方法行不通。 (a?1:0) 的解决方案是最接近你在 C 中建议的 Java 等效方法。我相信人们可以无休止地辩论其相对优点。在 C 中,你可以通过将布尔值视为整数来轻松缩短代码;在 Java 中,你受到保护,以免意外将布尔值视为整数而自己受伤。 - Jay

3
他可能不需要像按位比较运算符那样复杂的东西(通常不复杂,但在布尔值中使用按位运算符非常奇怪),也不需要像将其转换为整数并将它们相加这样非常迂回的方法。
最直接和自然的解决方法是使用以下表达式:
a ? (b || c): (b && c)

如果您喜欢,可以将其放入函数中,但它并不是非常复杂。解决方案在逻辑上简洁高效。


3

应该是:

(a || b && c) && (b || c && a)

此外,如果true自动转换为1false转换为0

(a + b*c) * (b + c*a) > 0

3

仅供参考,这只是完整加法器的一部分。在硬件上,您可以使用逻辑努力来确定基于不同布尔表达式的最佳电路。我猜传统的异或解决方案需要比帖子中提出的不太简洁的表达式更多的努力。


3
在Ruby中: [a, b, c].count { |x| x } >= 2 这可以在JavaVM上的JRuby中运行。;-)

2

这不是关于性能方面的问题,而是好的代码(可扩展和易于阅读的可重用代码)。

     static boolean trueBooleans (int howMany,boolean ... bools)
     {
      int total = 0;

      for (boolean b:bools)
        if (b && (++total == howMany)) return true;


      return false;
    }

在我看来,编写Java程序时,易于处理意外变化和没有重复代码比简洁(脚本语言的领域)或快速的程序更重要。


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;
        }
}

这个解决方案是否像其他一些解决方案那样酷?不是。但它更易于理解吗?是的。这会导致更可维护、更少错误的代码吗?是的。


2
为什么不直接使用 return ($count >= 2); 呢?此外,这个答案已经有人回答过了 - https://dev59.com/L3A75IYBdhLWcg3w1s32#3076954 - ChrisF
@iflytekif () {return bool} 对我来说更清晰。我可以理解有些人认为它太啰嗦了。我的解决方案与 https://dev59.com/L3A75IYBdhLWcg3w1s32#3076954 非常相似,但更完整,并包含一些理由(关于三元运算符令人困惑的文本)。 - labratmatt
5
就我个人而言,相对于三目运算符,我认为多个if语句更容易让我思考,因为每一个if语句都代表着不同的执行路径。然而,相比之下,一条单独的代码行只会在赋值符号左侧设置一次值,无论赋值符号右侧使用了多少个三目运算符。 - Jeremy Friesner
4
我更喜欢三元运算符而不是替换成多行的东西。 在传统代码中,我经常用三元运算符将 ~10 行缩减为一行。较少的文本=屏幕上更多的代码=更多的上下文。 - Luciano
2
是的,伙计……这不仅仅是为了酷炫。三元运算符更加简洁。少读点,少理解点。除非你真的很难理解它们,一个小小的三元运算符比起那8行代码和分支机会来说要快得多。 - mpen
这比三元运算符难理解得多。 - David Conrad

2
最佳答案应该是:“作为员工,重要的是我写得清晰明了,同时在必要时保持效率以提高绩效。” 这是我的写法:
function atLeastTwoAreTrue(a, b, c) {
    return (a && b) || (b && c) || (a && c);
}

实际上,测试是如此刻意的,以至于编写最快、最神秘的方法是完全可以接受的,只要您用简单的注释进行说明。 但总的来说,在这个一行代码的世界中,我们需要更加可读的代码。 :-)


2
在我的脑海中,C# 的意思是:
public bool lol(int minTrue, params bool[] bools)
{
    return bools.Count( ( b ) => b ) >= minTrue;
}

应该很快。

一个电话会是这样:

lol( 2, true, true, false );

这样,你让调用者自己决定规则(必须满足两个条件),而不是将规则嵌入方法中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接