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

我的解决方案如下:

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

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


当前回答

下面是使用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;
}

其他回答

我认为最简单的解决方法是:

返回(a && b) || c;

最明显的改进是:

// There is no point in an else if you already returned.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    return false;
}

然后

// There is no point in an if(true) return true otherwise return false.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return ((a && b) || (b && c) || (a && c));
}

但这些改进都是微不足道的。

总结一下。它被称为布尔代数是有原因的:

  0 x 0 = 0
  1 x 0 = 0
  1 x 1 = 1

  0 + 0 = 0
  1 + 0 = 1
  1 + 1 = 0 (+ carry)

如果你看那里的真值表,你可以看到乘法是布尔和,而简单的加法是异或。

回答你的问题:

return (a + b + c) >= 2

C解。

int two(int a, int b, int c) {
  return !a + !b + !c < 2;
}

或者你可能更喜欢:

int two(int a, int b, int c) {
  return !!a + !!b + !!c >= 2;
}

X = OR(a+b,c)

a b c X

1, 1, 0, 1

0, 0, 1, 1

0, 1, 1, 1