提问人: 提问时间:6/19/2010 最后编辑:7 revs, 6 users 49%user282886 更新时间:11/21/2023 访问量:199749
检查至少三分之二的布尔值是否为真
Check if at least two out of three booleans are true
问:
一位面试官最近问了我这个问题:给定三个布尔变量 a、b 和 c,如果这三个变量中至少有两个为真,则返回 true。
我的解决方案如下:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if ((a && b) || (b && c) || (a && c)) {
return true;
}
else{
return false;
}
}
他说,这可以进一步改进,但如何改进呢?
答:
而不是写:
if (someExpression) {
return true;
} else {
return false;
}
写:
return someExpression;
至于表达本身,像这样:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
return a ? (b || c) : (b && c);
}
或者这个(以你觉得更容易掌握的为准):
boolean atLeastTwo(boolean a, boolean b, boolean c) {
return a && (b || c) || (b && c);
}
它测试并且只测试一次,最多一次。a
b
c
引用
评论
return hasGoodAttendance ? (passedCoursework || passed Exam) : (passedCoursework && passedExam)
atLeastTwo(hasgoodAttendance, passedCoursework, passedExam)
为什么不从字面上实现呢?:)
(a?1:0)+(b?1:0)+(c?1:0) >= 2
在C语言中,你可以直接写(或者为了非常安全)。a+b+c >= 2
!!a+!!b+!!c >= 2
针对 TofuBeer 对 java 字节码的比较,这里做一个简单的性能测试:
class Main
{
static boolean majorityDEAD(boolean a,boolean b,boolean c)
{
return a;
}
static boolean majority1(boolean a,boolean b,boolean c)
{
return a&&b || b&&c || a&&c;
}
static boolean majority2(boolean a,boolean b,boolean c)
{
return a ? b||c : b&&c;
}
static boolean majority3(boolean a,boolean b,boolean c)
{
return a&b | b&c | c&a;
}
static boolean majority4(boolean a,boolean b,boolean c)
{
return (a?1:0)+(b?1:0)+(c?1:0) >= 2;
}
static int loop1(boolean[] data, int i, int sz1, int sz2)
{
int sum = 0;
for(int j=i;j<i+sz1;j++)
{
for(int k=j;k<j+sz2;k++)
{
sum += majority1(data[i], data[j], data[k])?1:0;
sum += majority1(data[i], data[k], data[j])?1:0;
sum += majority1(data[j], data[k], data[i])?1:0;
sum += majority1(data[j], data[i], data[k])?1:0;
sum += majority1(data[k], data[i], data[j])?1:0;
sum += majority1(data[k], data[j], data[i])?1:0;
}
}
return sum;
}
static int loop2(boolean[] data, int i, int sz1, int sz2)
{
int sum = 0;
for(int j=i;j<i+sz1;j++)
{
for(int k=j;k<j+sz2;k++)
{
sum += majority2(data[i], data[j], data[k])?1:0;
sum += majority2(data[i], data[k], data[j])?1:0;
sum += majority2(data[j], data[k], data[i])?1:0;
sum += majority2(data[j], data[i], data[k])?1:0;
sum += majority2(data[k], data[i], data[j])?1:0;
sum += majority2(data[k], data[j], data[i])?1:0;
}
}
return sum;
}
static int loop3(boolean[] data, int i, int sz1, int sz2)
{
int sum = 0;
for(int j=i;j<i+sz1;j++)
{
for(int k=j;k<j+sz2;k++)
{
sum += majority3(data[i], data[j], data[k])?1:0;
sum += majority3(data[i], data[k], data[j])?1:0;
sum += majority3(data[j], data[k], data[i])?1:0;
sum += majority3(data[j], data[i], data[k])?1:0;
sum += majority3(data[k], data[i], data[j])?1:0;
sum += majority3(data[k], data[j], data[i])?1:0;
}
}
return sum;
}
static int loop4(boolean[] data, int i, int sz1, int sz2)
{
int sum = 0;
for(int j=i;j<i+sz1;j++)
{
for(int k=j;k<j+sz2;k++)
{
sum += majority4(data[i], data[j], data[k])?1:0;
sum += majority4(data[i], data[k], data[j])?1:0;
sum += majority4(data[j], data[k], data[i])?1:0;
sum += majority4(data[j], data[i], data[k])?1:0;
sum += majority4(data[k], data[i], data[j])?1:0;
sum += majority4(data[k], data[j], data[i])?1:0;
}
}
return sum;
}
static int loopDEAD(boolean[] data, int i, int sz1, int sz2)
{
int sum = 0;
for(int j=i;j<i+sz1;j++)
{
for(int k=j;k<j+sz2;k++)
{
sum += majorityDEAD(data[i], data[j], data[k])?1:0;
sum += majorityDEAD(data[i], data[k], data[j])?1:0;
sum += majorityDEAD(data[j], data[k], data[i])?1:0;
sum += majorityDEAD(data[j], data[i], data[k])?1:0;
sum += majorityDEAD(data[k], data[i], data[j])?1:0;
sum += majorityDEAD(data[k], data[j], data[i])?1:0;
}
}
return sum;
}
static void work()
{
boolean [] data = new boolean [10000];
java.util.Random r = new java.util.Random(0);
for(int i=0;i<data.length;i++)
data[i] = r.nextInt(2) > 0;
long t0,t1,t2,t3,t4,tDEAD;
int sz1 = 100;
int sz2 = 100;
int sum = 0;
t0 = System.currentTimeMillis();
for(int i=0;i<data.length-sz1-sz2;i++)
sum += loop1(data, i, sz1, sz2);
t1 = System.currentTimeMillis();
for(int i=0;i<data.length-sz1-sz2;i++)
sum += loop2(data, i, sz1, sz2);
t2 = System.currentTimeMillis();
for(int i=0;i<data.length-sz1-sz2;i++)
sum += loop3(data, i, sz1, sz2);
t3 = System.currentTimeMillis();
for(int i=0;i<data.length-sz1-sz2;i++)
sum += loop4(data, i, sz1, sz2);
t4 = System.currentTimeMillis();
for(int i=0;i<data.length-sz1-sz2;i++)
sum += loopDEAD(data, i, sz1, sz2);
tDEAD = System.currentTimeMillis();
System.out.println("a&&b || b&&c || a&&c : " + (t1-t0) + " ms");
System.out.println(" a ? b||c : b&&c : " + (t2-t1) + " ms");
System.out.println(" a&b | b&c | c&a : " + (t3-t2) + " ms");
System.out.println(" a + b + c >= 2 : " + (t4-t3) + " ms");
System.out.println(" DEAD : " + (tDEAD-t4) + " ms");
System.out.println("sum: "+sum);
}
public static void main(String[] args) throws InterruptedException
{
while(true)
{
work();
Thread.sleep(1000);
}
}
}
这在我的机器上打印以下内容(在 Intel Core 2 + sun java 1.6.0_15-b03 上运行 Ubuntu 和 HotSpot Server VM(14.1-b02,混合模式)):
第一次和第二次迭代:
a&&b || b&&c || a&&c : 1740 ms
a ? b||c : b&&c : 1690 ms
a&b | b&c | c&a : 835 ms
a + b + c >= 2 : 348 ms
DEAD : 169 ms
sum: 1472612418
后续迭代:
a&&b || b&&c || a&&c : 1638 ms
a ? b||c : b&&c : 1612 ms
a&b | b&c | c&a : 779 ms
a + b + c >= 2 : 905 ms
DEAD : 221 ms
我想知道,java VM会做些什么来降低(a + b + c >= 2)情况下的性能。
以下是如果我使用 VM 交换机运行 java 会发生什么:-client
a&&b || b&&c || a&&c : 4034 ms
a ? b||c : b&&c : 2215 ms
a&b | b&c | c&a : 1347 ms
a + b + c >= 2 : 6589 ms
DEAD : 1016 ms
神秘。。。
如果我在 GNU Java Interpreter 中运行它,它会慢近 100 倍,但版本会获胜。a&&b || b&&c || a&&c
Tofubeer 使用运行 OS X 的最新代码的结果:
a&&b || b&&c || a&&c : 1358 ms
a ? b||c : b&&c : 1187 ms
a&b | b&c | c&a : 410 ms
a + b + c >= 2 : 602 ms
DEAD : 161 ms
Paul Wagland 使用 Mac Java 的结果 1.6.0_26-b03-383-11A511
a&&b || b&&c || a&&c : 394 ms
a ? b||c : b&&c : 435 ms
a&b | b&c | c&a : 420 ms
a + b + c >= 2 : 640 ms
a ^ b ? c : a : 571 ms
a != b ? c : a : 487 ms
DEAD : 170 ms
评论
a+b+c >= 2
:这不适用于负面因素,对吧?你可能不得不做这件事,我不确定。!!a
最明显的一组改进是:
// 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));
}
但这些改进是微不足道的。
您不需要使用运算符的短路形式。
return (a & b) | (b & c) | (c & a);
这执行的逻辑操作数量与您的版本相同,但完全无分支。
评论
可读性应该是目标。阅读代码的人必须立即理解您的意图。所以这是我的解决方案。
int howManyBooleansAreTrue =
(a ? 1 : 0)
+ (b ? 1 : 0)
+ (c ? 1 : 0);
return howManyBooleansAreTrue >= 2;
评论
Seq(true, true, false).map(if (_) 1 else 0).sum >= 2
这类问题可以用卡诺地图来解决:
| 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
评论
在这里获取答案(到目前为止):
public class X
{
static boolean a(final boolean a, final boolean b, final boolean c)
{
return ((a && b) || (b && c) || (a && c));
}
static boolean b(final boolean a, final boolean b, final boolean c)
{
return a ? (b || c) : (b && c);
}
static boolean c(final boolean a, final boolean b, final boolean c)
{
return ((a & b) | (b & c) | (c & a));
}
static boolean d(final boolean a, final boolean b, final boolean c)
{
return ((a?1:0)+(b?1:0)+(c?1:0) >= 2);
}
}
并通过反编译器运行它们(javap -c X >结果.txt):
Compiled from "X.java"
public class X extends java.lang.Object{
public X();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
static boolean a(boolean, boolean, boolean);
Code:
0: iload_0
1: ifeq 8
4: iload_1
5: ifne 24
8: iload_1
9: ifeq 16
12: iload_2
13: ifne 24
16: iload_0
17: ifeq 28
20: iload_2
21: ifeq 28
24: iconst_1
25: goto 29
28: iconst_0
29: ireturn
static boolean b(boolean, boolean, boolean);
Code:
0: iload_0
1: ifeq 20
4: iload_1
5: ifne 12
8: iload_2
9: ifeq 16
12: iconst_1
13: goto 33
16: iconst_0
17: goto 33
20: iload_1
21: ifeq 32
24: iload_2
25: ifeq 32
28: iconst_1
29: goto 33
32: iconst_0
33: ireturn
static boolean c(boolean, boolean, boolean);
Code:
0: iload_0
1: iload_1
2: iand
3: iload_1
4: iload_2
5: iand
6: ior
7: iload_2
8: iload_0
9: iand
10: ior
11: ireturn
static boolean d(boolean, boolean, boolean);
Code:
0: iload_0
1: ifeq 8
4: iconst_1
5: goto 9
8: iconst_0
9: iload_1
10: ifeq 17
13: iconst_1
14: goto 18
17: iconst_0
18: iadd
19: iload_2
20: ifeq 27
23: iconst_1
24: goto 28
27: iconst_0
28: iadd
29: iconst_2
30: if_icmplt 37
33: iconst_1
34: goto 38
37: iconst_0
38: ireturn
}
你可以看到?:比你原来的修复版本稍微好一些。最好的是完全避免分支的那个。从指令较少(在大多数情况下)的角度来看,这是件好事,并且对于 CPU 的分支预测部分更好,因为分支预测中的错误猜测会导致 CPU 停滞。
我想说最有效的是 moonshadow 整体上的那个。它平均使用最少的指令,并减少了 CPU 中管道停顿的机会。
为了 100% 确定,您需要找出每条指令的成本(以 CPU 周期为单位),不幸的是,这并不容易获得(您必须查看热点的来源,然后查看 CPU 供应商的规格,了解每个生成的指令所花费的时间)。
请参阅 Rotsor 更新的答案,了解代码的运行时分析。
评论
boolean atLeastTwo(boolean a, boolean b, boolean c)
{
return ((a && b) || (b && c) || (a && c));
}
直接代码的另一个示例:
int n = 0;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 2);
显然,这不是最简洁的代码。
补遗
另一个(略微优化的)版本:
int n = -2;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 0);
假设与 0 的比较将比与 2 的比较使用更快(或更少)的代码,这可能会运行得稍微快一些。
评论
n
++
下面是一个测试驱动的通用方法。不像迄今为止提供的大多数解决方案那样“高效”,但清晰、经过测试、有效且通用。
public class CountBooleansTest extends TestCase {
public void testThreeFalse() throws Exception {
assertFalse(atLeastTwoOutOfThree(false, false, false));
}
public void testThreeTrue() throws Exception {
assertTrue(atLeastTwoOutOfThree(true, true, true));
}
public void testOnes() throws Exception {
assertFalse(atLeastTwoOutOfThree(true, false, false));
assertFalse(atLeastTwoOutOfThree(false, true, false));
assertFalse(atLeastTwoOutOfThree(false, false, true));
}
public void testTwos() throws Exception {
assertTrue(atLeastTwoOutOfThree(false, true, true));
assertTrue(atLeastTwoOutOfThree(true, false, true));
assertTrue(atLeastTwoOutOfThree(true, true, false));
}
private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) {
return countBooleans(b, c, d) >= 2;
}
private static int countBooleans(boolean... bs) {
int count = 0;
for (boolean b : bs)
if (b)
count++;
return count;
}
}
评论
这是另一个使用 map/reduce 的实现。这在分布式环境中可以很好地扩展到数十亿布尔©值。使用 MongoDB:
创建布尔值数据库:values
db.values.insert({value: true});
db.values.insert({value: false});
db.values.insert({value: true});
创建地图,reduce功能:
编辑:我喜欢 CurtainDog 关于将 map/reduce 应用于通用列表的回答,所以这里有一个 map 函数,它接受一个回调来确定是否应该计算一个值。
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;
}
评论
还有另一种方法可以做到这一点,但不是很好的方法:
return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);
哈希码值固定为 1231 表示 true,1237 表示 false,因此同样可以使用Boolean
<= 3699
评论
最简单的方法(IMO)不会混淆且易于阅读:
// Three booleans, check if two or more are true
return ( a && ( b || c ) ) || ( b && c );
评论
(C && (A || B)) || (A && B)
三元运算符让书的汁液流动起来,但它们可能会令人困惑(使代码的可维护性降低,从而增加了错误注入的可能性)。杰夫·阿特伍德(Jeff Attwood)在这里说得很好:
这是权衡的一个完美例子 一次完全没有意义的 节省了数十个写入时间 阅读时间理解惩罚 -- 它 让我思考。
为了避免使用三元运算符,我创建了以下函数:
function atLeastTwoTrue($a, $b, $c) {
$count = 0;
if ($a) { $count++; }
if ($b) { $count++; }
if ($c) { $count++; }
return $count >= 2;
}
这是否与其他一些解决方案一样酷?不。更容易理解吗?是的。这会导致更易于维护、更少的错误代码吗?是的。
评论
return ($count >= 2);
Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
{
return (System.Convert.ToInt16(val1) +
System.Convert.ToInt16(val2) +
System.Convert.ToInt16(val3)) > 1;
}
执行此操作的方法太多了......
评论
我不喜欢三元(从顶部答案开始),而且我认为我没有看到有人提到它。它是这样写的:return a ? (b || c) : (b && c);
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if (a) {
return b||c;
}
else {
return b&&C;
}
只是为了用XOR来回答一个相对直接的问题......
return a ^ b ? c : a
评论
function atLeastTwoTrue($a, $b, $c) { int count = 0; count = (a ? count + 1 : count); count = (b ? count + 1 : count); count = (c ? count + 1 : count); return (count >= 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;
}
return 1 << $a << $b << $c >= 1 << 2;
评论
总结一下。它被称为布尔代数是有原因的:
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
评论
return ((a?1:0) + (b?1:0) + (c?1:0)) >= 2
我的第一个想法是
return (a||b)&&(b||c)
但为了便于阅读,我喜欢你们建议的更好的 a+b+c>=2 解决方案
评论
这绝对是一个关于你如何解决问题/思考的问题,而不是你的实际编码能力。
稍微简洁的版本可能是
返回 ((a ^ b) && (b ^ c)) ^ b
但就像之前的海报所说的那样,如果我在我正在处理的任何代码中看到这一点,就会有人听到。:)
字面解释适用于所有主要语言:
return (a ? 1:0) + (b ? 1:0) + (c ? 1:0) >= 2;
但我可能会让人们更容易阅读,并扩展到三个以上——这似乎被许多程序员遗忘了:
boolean testBooleans(Array bools)
{
int minTrue = ceil(bools.length * .5);
int trueCount = 0;
for(int i = 0; i < bools.length; i++)
{
if(bools[i])
{
trueCount++;
}
}
return trueCount >= minTrue;
}
我想我还没有看到这个解决方案:
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 个是真的”,而前两个值实际上是真的,那么它应该比一些更“正常”的解决方案更快。
评论
boolean ... boolValues
在 Clojure 中:
(defn at-least [n & bools]
(>= (count (filter true? bools)) n)
用法:
(at-least 2 true false true)
评论
X = 或(a+b,c)
a b c X
1 1 0 1
0 0 1 1
0 1 1 1
评论
如果目标是为三个操作数返回按位三分之二的值,则算术和迭代方法往往相对无效。在许多 CPU 架构上,一个好的形式是“return ((a |b) & c) |(a&b);”。这需要四个布尔运算。在单累加器机器(常见于小型嵌入式系统)上,每字节总共需要 7 条指令。表格“return (a & b) |(a&c) |(b&c);”也许看起来更好,但它需要五个布尔运算,或者在单个累加器机器上每字节九个指令。
顺便说一句,在CMOS逻辑中,计算“不是三分之二”需要12个晶体管(相比之下,一个逆变器需要两个,一个双输入NAND或NOR需要4个,一个3输入NAND或NOR需要6个)。
我相信使用普通的布尔运算符 (a || b) && (b || c) 很好,而且更简单。
您可以将 3 个字母中的任何一个与其他两个字母中的任何一个交换,并且它仍然是相同的表达。
评论
我没有看到其他人指出的一件事是,在求职面试的“请给我写一些代码”部分的标准做法是,当你说你完成了时,说“你能改进吗?”或者“你对此完全满意吗”或“这是否尽可能优化?您可能会听到“您将如何改进”,因为“这可能会得到改进;如何?在这种情况下,将成语更改为 just 是一种改进 - 但请注意,有时他们只是想看看您对问题的反应。我听说有些面试官会坚持认为完美的代码存在缺陷,只是为了看看你如何应对它。if(x) return true; else return false;
return x
这种读起来更好:
if (a) {
return b || c;
}
else {
return b && c;
}
这个问题的最佳答案应该是“作为一名员工,重要的是我写它,这样我的意思才能清晰,同时在必要时保持效率。我是这样写的:
function atLeastTwoAreTrue(a, b, c) {
return (a && b) || (b && c) || (a && c);
}
实际上,这个测试是如此人为,以至于如果你用一个简单的注释来适应它,那么编写一个最快、最神秘的方法是完全可以接受的。但是,总的来说,在这个单行世界中,我们需要在这个世界上具有更多可读性的代码。:-)
通过真值表计算:
return (a & b) | (c & (a ^ b));
评论
return (a==b) ? a : c;
解释:
如果 ,则两者都为真或两者都为假。如果两者都为真,则我们已找到两个真布尔值,并且可以返回 true(通过返回 )。如果两者都为 false,则即使为 true,也不能有两个 true 布尔值,因此我们返回 false(通过返回 )。这就是部分。怎么样?好吧,如果为假,那么恰好有一个或必须为真,所以我们找到了第一个真布尔值,唯一重要的是如果也是真的,所以我们返回作为答案。a==b
a
c
a
(a==b) ? a
: c
a==b
a
b
c
c
评论
a
b
c
仅供参考,这只是一个完整加法器的执行位。在硬件中,您可以使用逻辑工作量根据不同的布尔表达式确定最佳电路。我猜想,传统的异或解决方案会比海报所呈现的不那么简洁的表达需要更多的努力。
在 C# 中,从我的头顶上:
public bool lol(int minTrue, params bool[] bools)
{
return bools.Count( ( b ) => b ) >= minTrue;
}
应该很快。
呼叫如下所示:
lol( 2, true, true, false );
这样,您将规则(两个必须为 true)留给调用者,而不是将它们嵌入到方法中。
作为 @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 成为整体上最快的(在我的 HP/Intel 笔记本电脑上)。
这真的取决于你所说的“改进”是什么意思:
清晰?
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.
哪一个是“改进”,很大程度上取决于情况。
int count = 0;
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if (a)
count++;
if (b)
count++;
if (c)
count++;
return count > 1;
}
在 Ruby 中:
[a, b, c].count { |x| x } >= 2
它可以在 JavaVM 上的 JRuby 中运行。;-)
所提问题中的 2 和 3 绝对是神奇的数字。“正确”的答案将取决于面试官是否试图掌握布尔逻辑(我认为 pdox 的答案在这方面无法胜过)或你对架构问题的理解。
我倾向于使用map-reduce解决方案,该解决方案将接受具有任意条件的任何类型的列表。
我找到了这个解决方案。
boolean atLeastTwo(boolean a, boolean b, boolean c) {
bool result = !(a ^ b ^ c) && !(!a & !b & !c) || (a & b & c);
return result;
}
当我看到这个问题时,我的第一个想法是:
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;
多样性,因为 is 更容易扩展。如果稍后我们添加必须测试的第四个变量怎么办?如果变量的数量是在运行时确定的,并且我们被传递了一个未知大小的布尔数组,该怎么办?依赖于计数的解决方案比依赖于列出每个可能的组合的解决方案更容易扩展。此外,在列出所有可能的组合时,我怀疑更容易犯错误。就像尝试为“任意 3 个中的 4 个”编写代码一样,并确保您既不会遗漏任何代码,也不会重复任何代码。现在尝试使用“任意 5 个中的 7”。
评论
他可能不是在寻找任何复杂的东西,比如按位比较运算符(通常不是错综复杂的,但有布尔值,使用按位运算符非常奇怪)或非常迂回的东西,比如转换为 int 并将它们相加。
解决这个问题最直接、最自然的方法是用这样的表达方式:
a ? (b || c): (b && c)
如果您愿意,可以将其放在函数中,但它不是很复杂。该解决方案在逻辑上简洁而高效。
设三个布尔值分别为 A、B 和 C。
您可以使用 k-MAP 并附带布尔表达式。
在本例中,布尔表达式将是A(B+C) + C
return (A && (B || C )) || C;
评论
C:
if (!!a + !!b + !!c >= 2)
它应该是:
(a || b && c) && (b || c && a)
此外,if 会自动转换为 和 :true
1
false
0
(a + b*c) * (b + c*a) > 0
在我看来,三分之二是相当任意的数字,该函数应该与任意数字一起使用。因此,为了回答这个问题,我会编写一个函数来计算数组中的 x 是否为真,例如,
bool istrue ( int x, bool[] list)
y = count true in list
return y >= x
在 C 中:
return !!a + !!b + !!c >= 2;
评论
我们可以将布尔值转换为整数并执行以下简单检查:
(int(a) + int(b) + int(c)) >= 2
评论
a+b+c>=2
此问题的非简化解决方案是:
a'bc + abc' + abc + ab'c
减少使用 K-Maps,可以得到:
bc + ab + ac
可以通过在 a'bc 和 abc 最小项上使用 exclusive 或并结合 abc 和 ab'c 最小项来进一步减少这种情况:
b(a ^ c) + ac
怎么样 - Java,使用三个比较而不是 OP 的六个。(a||b) && (a||c)
错了,我应该早点检查。
评论
由于没有具体说明如何改进代码,我将努力改进代码,使其更有趣。这是我的解决方案:
boolean atLeastTwo(boolean t, boolean f, boolean True) {
boolean False = True;
if ((t || f) && (True || False))
return "answer" != "42";
if (t && f)
return !"France".contains("Paris");
if (False == True)
return true == false;
return Math.random() > 0.5;
}
如果有人想知道这段代码是否有效,这里有一个使用相同逻辑的简化:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if ((a || b) && (c))
return true;
if (a && b)
return true;
if (true)
return false;
// The last line is a red herring, as it will never be reached:
return Math.random() > 0.5;
}
这可以进一步归结为以下几点:
return ((a || b) && (c)) || (a && b);
但现在它不再好笑了。
如果我将布尔值转换为一个数字,并且该数字不是 2 的幂,则它至少有两个真。
a*4 + b*2 + c*1 = N
return( N != 0 && (N&(N-1)) != 0)
我只是给出一个替代方案。
使用三元运算符解决问题的最简单形式是:
return a ? (b ? true : c) : (b ? c : false);
您可能还想通过使用对要求的双重否定来投资寻找解决方案,这意味着,您最多需要满足一个假值,而不是至少两个真值。
评论
a ? b||c : b&&c
不是在性能的上下文中,而是在好的代码(可扩展和可读的代码,可以重用)
static boolean trueBooleans (int howMany,boolean ... bools)
{
int total = 0;
for (boolean b:bools)
if (b && (++total == howMany)) return true;
return false;
}
以我的拙见,在编写 Java 时,易于处理意外更改和没有重复代码比简洁(脚本语言领域)或快速程序更重要。
函数返回答案:ko
static int ho(bool a)
{
return a ? 1 : 0;
}
static bool ko(bool a, bool b, bool c)
{
return ho(a) + ho(b) + ho(c) >= 2;
}
评论
这个怎么样:
(a - b) ? c : a
评论
我认为最简单的解决方案是:
return (a && b) || c;
评论
使用 Java 8 的 Stream 功能采取另一种方法,用于任意数量的具有任意所需数量的布尔值。如果 Stream 在处理所有元素之前达到限制,则会短路:
public static boolean atLeastTrue(int amount, Boolean ... booleans) {
return Stream.of(booleans).filter(b -> b).limit(amount).count() == amount;
}
public static void main(String[] args){
System.out.println("1,2: " + atLeastTrue(1, true, false, true));
System.out.println("1,1: " + atLeastTrue(1, false, true));
System.out.println("1,0: " + atLeastTrue(1, false));
System.out.println("1,1: " + atLeastTrue(1, true, false));
System.out.println("2,3: " + atLeastTrue(2, true, false, true, true));
System.out.println("3,2: " + atLeastTrue(3, true, false, true, false));
System.out.println("3,3: " + atLeastTrue(3, true, true, true, false));
}
输出:
1,2: true
1,1: true
1,0: false
1,1: true
2,3: true
3,2: false
3,3: true
public static boolean atLeast(int atLeastToBeTrue, boolean...bools){
int booleansTrue = 0;
for(boolean tmp : bools){
booleansTrue += tmp ? 1 : 0;
}
return booleansTrue >= atLeastToBeTrue;
}
你可以从a.k.a中选择你想要多少是真实的:-)at least
varargs
boolean[]
目前使用 Java 8,我真的很喜欢这样的东西:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
return Stream.of(a, b, c).filter(active -> active).count() >= 2;
}
评论
Arrays.asList(a, b, c).stream()
Stream.of(a, b, c)
另一个:
return a? b||c : b&&c
评论
在算术运算的帮助下,这非常简单。
boolean a = true;
boolean b = false;
boolean c = true;
// Exactly one boolean value true.
return (a?1:0)+(b?1:0)+(c?1:0)==1;
// Exactly 2 boolean value true.
return (a?1:0)+(b?1:0)+(c?1:0)==2;
这就是您可以增加常量值以检查有多少布尔值的方法。true
如果您有很多布尔值,则很容易遇到运算符重载。
operator fun Boolean.unaryPlus() = if (this) 1 else 0
// ...
if(+bool1 + +bool2 + ... + +boolN > 2) {
// ...
}
上一个:Pandas 中的元素逻辑 OR
评论
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou)
atLeastTwo(0,2,0)