알고리즘/프로그래머스

[프로그래머스/JAVA] 비밀지도 - 2018 KAKAO BLIND RECRUITMENT

Heony 2022. 1. 14. 10:17

2018 KAKAO BLIND RECRUITMENT의 LEVEL 1 문제이다.

저번에 배웠던 비트 연산자의 응용이라고 할 수 있겠다. 이걸 어디다가 쓰지 하면서도 막상 문제로 나오니 감사합니다 하면서 풀었던 것 같다. 이 문제의 핵심은 비트 연산자를 어떻게 활용하냐도 있겠지만, 그 경우의 수에 따라서 어떤 연산자를 사용할지, 연산자를 사용하여 나온 값으로 어떻게 가공할지에 대한 논의도 필요해 보인다.

본 문제에서는 AND연산자가 아닌 OR연산자로 arr1과 arr2에서 한번도 나오지 않은 부분들에 대해 체크하고, 그 부분들을 공백으로 처리함으로써 문제를 풀어야 했다. 다음은 내 코드이다.

import java.util.*;
class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        int[] arr = new int[n];
        for(int i = 0; i < n; i++) {
            /* 비트연산자의 활용 */
            int a = arr1[i] | arr2[i];
            StringBuilder sb = new StringBuilder();
            for(int j = n - 1; j >= 0; j--) {
                /* 해당 비트와 1과 AND로 비교했을 때 0이 아니라면 값이 있는 것 */
                if((a & (1 << j)) != 0) sb.append("#");
                else sb.append(" ");
            }
            answer[i] = sb.toString();
        }
        return answer;
    }
}

arr1[i] | arr2[i] 연산자는, 앞에서 나온 값과 뒤에서 나온 값을 OR처리하여 두 배열에서 나오지 않은 값들에 대해 0으로 처리하는 의미를 가졌다. 예를 들어, 00110과 01011이 OR처리 되면 01111과 같은 값이 나온다. 이것은 이론이지만 JAVA에서 실제 값으로 처리할 때에는 조금 다르다.

int a = arr1[i] | arr2[i] 에서 arr1[i] 값으로 00110이 들어가는 것이 아니라 10진법으로 들어가게 된다. 00110(2) = 6이므로 arr1[i]는 6이 들어간다고 생각하면 되고, arr2[i] 값으로 01011이니 11로 들어가게 된다. 따라서 int a = 6 | 11 이라는 의미이고 저것이 비트 연산자를 통해 들어가게 되면 2진법을 통해 연산이 되어 a의 값으로 다시 10진법을 통해 나오게 된다. 즉 a는 01111(2)인 15가 나온다.

근데 15라는 값으로 어떻게 어디에 1비트인지 0비트인지 확인할 수 있을까?
여기서도 비트 연산자가 필요로하다. 1이라는 값을 << 연산자를 통해 해당 길이만큼 넣는다. 즉, 1 << 4를 하게 되면 2진법으로 표현하게 되었을 때 10000(2)이 된다. 그러면 15라는 값(01111)과 1<<4(10000)값이 and처리가 되어 0이 처리된곳은 다 무시하고 1을 집어넣었던 그 자리수에서만 비교를 했을 때, 0이 아닌수가 나왔다는 것은 그 자리에 1이 들어가있다는 것을 의미한다. 15 & (1 << 4)는 물론 0이다. 15는 01111 이니까.

하지만, 15 & (1 << 3)은 01111과 01000은 1이 겹치므로 01000의 결과값 즉, 8이라는 결과값이 나오기 때문에 0이 아니다는 조건에 true가 나오게 된다. 이처럼 비교하여 StringBuilder에 값을 차곡차곡 넣어 answer의 답을 출력시키는 것이다.

728x90