한 면접관이 최근에이 질문을했습니다. 세 개의 부울 변수 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
대부분 한 번에.
참고 문헌
답변
XOR을 사용하여 비교적 간단한 문제에 대답하기 위해 …
return a ^ b ? c : a
답변
문자 그대로 구현하지 않겠습니까? 🙂
(a?1:0)+(b?1:0)+(c?1:0) >= 2
C에서는 작성 a+b+c >= 2
하거나 !!a+!!b+!!c >= 2
매우 안전 할 수 있습니다.
에 대한 응답으로 TofuBeer 자바 바이트 코드의 비교, 여기에 간단한 성능 테스트는 다음과 같습니다
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);
}
}
}
내 컴퓨터에서 다음을 인쇄합니다 (핫스팟 서버 VM (14.1-b02, 혼합 모드)으로 Intel Core 2 + sun java 1.6.0_15-b03에서 Ubuntu 실행) :
첫 번째와 두 번째 반복 :
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
(a + b + c> = 2) 사례에 대해 시간이 지남에 따라 성능 을 저하시키는 Java VM의 기능은 무엇입니까 ?
그리고 -client
VM 스위치로 java를 실행하면 어떻게됩니까?
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
버전이 승리합니다.
OS X를 실행하는 최신 코드를 사용한 Tofubeer의 결과 :
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
Mac Java 1.6.0_26-b03-383-11A511을 사용한 Paul Wagland의 결과
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
답변
이런 종류의 질문은 Karnaugh Map 으로 해결할 수 있습니다 .
| 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
답변
가독성이 목표가되어야합니다. 코드를 읽는 사람은 귀하의 의도를 즉시 이해해야합니다. 그래서 여기 내 해결책이 있습니다.
int howManyBooleansAreTrue =
(a ? 1 : 0)
+ (b ? 1 : 0)
+ (c ? 1 : 0);
return howManyBooleansAreTrue >= 2;
답변
return (a==b) ? a : c;
설명:
인 경우 a==b
둘 다 true이거나 둘 다 false입니다. 둘 다 true이면 두 개의 실제 부울을 찾은 후 true를 반환 할 수 있습니다 (을 반환하여 a
). 둘 다 거짓이면 참인 경우에도 두 개의 참 부울이있을 수 c
없으므로를 반환하여 거짓을 반환 a
합니다. 그 (a==b) ? a
부분입니다. 무엇에 대해 : c
? 음 a==b
이 거짓 이라면 , 정확히 하나 a
이거나 b
사실이어야합니다. 그래서 우리는 첫 번째 참 부울을 찾았습니다. 그리고 중요한 것은 남은 것이 c
사실이기도합니다. 그래서 우리 c
는 답으로 돌아갑니다 .
답변
단락 회로 연산자를 사용할 필요는 없습니다.
return (a & b) | (b & c) | (c & a);
이것은 버전과 동일한 수의 논리 연산을 수행하지만 완전히 분기가 없습니다.