양의 정수 x에 대한 함수 f(x)를 다음과 같이 정의합니다.
x보다 크고 x와 비트가 1~2개 다른 수들 중에서 제일 작은 수
예를 들어,
f(2) = 3 입니다. 다음 표와 같이 2보다 큰 수들 중에서 비트가 다른 지점이 2개 이하이면서 제일 작은 수가 3이기 때문입니다.
수 비트 다른 비트의 개수
2 : 000...0010
3 : 000...0011 1
f(7) = 11 입니다. 다음 표와 같이 7보다 큰 수들 중에서 비트가 다른 지점이 2개 이하이면서 제일 작은 수가 11이기 때문입니다.
수 비트 다른 비트의 개수
7 : 000...0111
8 : 000...1000 4
9 : 000...1001 3
10 : 000...1010 3
11 : 000...1011 2
정수들이 담긴 배열 numbers가 매개변수로 주어집니다. numbers의 모든 수들에 대하여 각 수의 f 값을 배열에 차례대로 담아 return 하도록 solution 함수를 완성해주세요.
1 ≤ numbers의 길이 ≤ 100,000
0 ≤ numbers의 모든 수 ≤ 1015
public class Test_55_NoMoreThan2Bits {
public long[] solution(long[] numbers) {
long[] answer = new long[numbers.length];
for (int i = 0; i < numbers.length; i++) {
answer[i] = findNextNum(numbers[i]);
}
return answer;
}
private long findNextNum(long x) {
long next = x + 1; // x보다 큰 수를 찾기 시작
while (true) {
// 비트 차이를 계산
long diff = x ^ next;
// 1의 개수 세기
if (countNum(diff) <= 2) {
return next; // 조건을 만족하면 반환
}
next++; // 다음 숫자로 이동
}
}
private int countNum(long n) {
int count = 0;
while (n > 0) {
count += (n & 1); // 마지막 비트 확인
n >>= 1; // 오른쪽으로 비트 이동
}
return count;
}
}
더이상의 시간복잡도를 개선할 방법을 찾기 어려워 구글링으로 다른 사람들의 코드를 찾아본 결과 여러 방법들이 있었고
그 중 가장 직관적이면서 좋아보이는 방법을 발견했다.
public class Test_55_NoMoreThan2Bits {
public long[] solution(long[] numbers) {
long[] answer = new long[numbers.length];
for (int i = 0; i<numbers.length; i++) {
long result = numbers[i];
String target = Long.toBinaryString(numbers[i]);
if (result % 2 == 0) {
answer[i] = result + 1;
} else {
int idx = target.lastIndexOf("0");
if (idx == -1) {
String tmp = "10" + target.substring(1);
answer[i] = Long.parseLong(tmp, 2);
} else {
String tmp = target.substring(0, idx) + "10" + target.substring(idx + 2);
answer[i] = Long.parseLong(tmp, 2);
}
}
}
return answer;
}
}