2 minute read



문제 풀이


이번 문제는 문제의 요구사항대로 비트를 활용해 구현하면 되는 문제이다.


아아디어 도출

비트연산자를 활용하면 풀 수 있을 것으로 보이나 필자는 비트연산에 대해서 부족한 점이 많아 규칙을 찾아서 풀었다.

정수를 비트(2진수)로 변환한 후, 이 수보다 큰 수이면서 비트일 때의 차이가 1~2개이여야 한다. 여기서 어떤 규칙을 찾아낼 수 있을까?

먼저 십진수 1부터 6까지를 비트로 표현해보자.

십진수/비트 16 8 4 2 1
1         1
2       1 0
3       1 1
4     1 0 0
5     1 0 1
6     1 1 0

잘보면 짝수일 때는 모두 0으로 끝나는 것을 알 수 있다. 그렇다면 여기서 짝수의 규칙을 찾아낼 수 있다!

짝수일 때의 규칙 비트의 끝자리가 0인, 즉 짝수인 십진수의 경우 +1인 값이 조건에 충족된다.
Ex. 2(10) -> 3(11), 4(100) -> 5(101), 6(110) -> 7(111)

짝수의 규칙은 쉽지만, 홀수의 규칙을 찾기가 어려웠다. 홀수의 경우는 끝자리가 1인데, 비트값을 기준으로 0이 섞인 홀수와 0이 없는 홀수로 나뉘게 된다.

홀수일 때의 규칙

  1. 0이 존재할 경우, 하위 비트에서부터 “01”을 찾아 “10”으로 바꾼다.
    Ex. 5(101) -> "1" + "10" = "110", 9(1001) -> "10" + "10" = "1010"
  2. 0이 없을 경우, 큰 수이면서 가까운 수이려면 상위비트에 0을 삽입한다.
    Ex. 7(111) -> "10" + "11" = "1011", 11111 -> "10" + "1111" => "101111"

위와 같이 주어진 수가 짝수일 경우와 홀수일 경우를 나누어 규칙을 반영하여 조건에 맞는 십진수를 배열에 담아 반환하면 된다.


다음으로 문제 풀이를 위해 작성한 코드는 아래와 같다.



작성 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Solution {

    public long[] solution(long[] numbers) {
    
        long[] answer = new long[numbers.length];

        for(int i=0; i<numbers.length; i++) {
            
            /*
             * numbers의 원소가 짝수일 경우
             * 해당 수의 바로 다음 비트는 다른 점이 1개이면서 큰 수라는 조건을 충족한다.
             * f(n) = n + 1
             */
            if(numbers[i] % 2 == 0) {
                answer[i] = numbers[i] + 1;
                continue;
            }
            
            /*
             * numbers의 원소가 홀수일 경우
             * 해당 수의 최하위 비트(마지막)부터 "01"을 찾아 "01"이 있다면, "10"으로 바꿔준다.
             * "01"이 없다면 최상위 비트(처음)를 제거하고 "10"을 추가한다.
             * 변환한 비트인 2진수를 Long형 타입으로 변환하여 배열에 삽입한다.
             */
            String binary = Long.toBinaryString(numbers[i]);
            
            // 해당 2진수에서 "01"의 인덱스를 마지막 비트에서부터 찾아 "10"으로 변환한다.
            int zeroIdx = binary.lastIndexOf("01");
            if(zeroIdx != -1) {
                binary = binary.substring(0, zeroIdx) + "10" + binary.substring(zeroIdx+2, binary.length());
                answer[i] = Long.parseLong(binary, 2);
                continue;
            }
            
            // "01"이 없다면 상위 비트 하나를 제거하고 "10"을 삽입한다.
            binary = "10" + binary.substring(1, binary.length());
            answer[i] = Long.parseLong(binary, 2);

        }

        return answer;
    }

    public static void main(String[] args) {
        
        Solution sol = new Solution();
        
        long[] numbers = new long[]{2, 7};
        // long[] numbers = new long[]{5, 7, 11};
        // long[] numbers = new long[]{1001,337}; // 1002, 338
        
        sol.solution(numbers);

    }

}

회고

-



출처

-


  • 해당 문제의 저작권은 문제를 만든이에게 있으며 자세한 내용은 문제 링크에서 참조바랍니다.