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

我的解决方案如下:

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

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


当前回答

当然,这个问题更多的是关于你如何解决问题/思考,而不是你实际的编码能力。

一个稍微简洁一点的版本可能是

返回((a ^ b) && (b ^ c)) ^ b

但就像之前的一个帖子说的,如果我在任何我正在编写的代码中看到这个,有人会听到很多。:)

其他回答

另一个:

return a? b||c : b&&c

这个问题的最佳答案应该是:“作为一名员工,我写出来的东西很重要,这样我的意思就能清楚地表达出来,同时又能保持绩效所需的效率。”我是这样写的:

function atLeastTwoAreTrue(a, b, c) {
    return (a && b) || (b && c) || (a && c);
}

在现实中,这个测试是如此的刻意,以至于如果您用一个简单的注释来容纳它,那么编写一个最快、最神秘的方法是完全可以接受的。但是,一般来说,在这个一行代码的世界里,我们需要更多可读的代码。: -)

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

      | 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

我想我还没见过这个解决方案:

boolean atLeast(int howMany, boolean[] boolValues) {
  // check params for valid values

  int counter = 0;
  for (boolean b : boolValues) {
    if (b) {
      counter++;

      if (counter == howMany) {
        return true;
      }
    }
  }
  return false;
}

它的优点是一旦达到你要找的数字,它就会崩溃。因此,如果这是“这1,000,000个值中至少有2个是真的”,而前两个值实际上是真的,那么它应该比一些更“正常”的解更快。

下面是使用map/reduce的另一个实现。在分布式环境中,这可以很好地扩展到数十亿布尔值©。使用MongoDB:

创建数据库的布尔值:

db.values.insert({value: true});
db.values.insert({value: false});
db.values.insert({value: true});

创建map, reduce函数:

编辑:我喜欢CurtainDog的回答有映射/减少适用于泛型列表,所以这里有一个地图函数,它接受一个回调,决定一个值是否应该被计数。

var mapper = function(shouldInclude) {
    return function() {
        emit(null, shouldInclude(this) ? 1 : 0);
    };
}

var reducer = function(key, values) {
    var sum = 0;
    for(var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}

运行map / reduce:

var result = db.values.mapReduce(mapper(isTrue), reducer).result;

containsMinimum(2, result); // true
containsMinimum(1, result); // false


function isTrue(object) {
    return object.value == true;
}

function containsMinimum(count, resultDoc) {
    var record = db[resultDoc].find().next();
    return record.value >= count;
}