S E P H ' S

[Java] 2개 이하로 다른 비트 본문

Algorithm/Programmers

[Java] 2개 이하로 다른 비트

yoseph0310 2023. 5. 15. 16:36
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 풀이

비트를 다루는데 생소하다면 연습해볼 좋은 문제이다. 문제의 조건이 비트를 다룰줄 알아야만 이해할 수 있는 조건이기 때문이다.

문제의 조건은 x에 대해서 x보다 크고 x와 비트가 1~2개 다른 수들 중에서 제일 작은 수이다.

 

숫자를 2진수로 변환해본다면 짝수는 무조건 뒷자리가 0이다. 따라서 1만 더해준다면 짝수는 조건에 해당하는 수를 금방 찾을 수 있다.

문제는 홀수이다. 홀수일때 조건을 만족하는 수들의 규칙을 찾는것이 어려웠다. x = 15라고 예시로 들어보겠다. 15를 2진수로 변환하면 01111 이다. x보다는 커야 한다고 했으므로 01110은 조건을 충족하는 숫자가 아니다. 그러므로 앞쪽의 비트를 바꿔줘야한다. 

01111 -> 10111 이라면 비트가 1~2개 다른 수이면서 x보다 크다. 

 

이를 구현하기 위해서는 연속된 1의 개수를 세야한다. 1의 개수를 cnt라고 해보자. 01111은 cnt가 4이다. 이제 01111에서 10111이 되기위해서는 얼마를 더해야할까? 01111에서 1000을 더한다면 10111이 될 것이다. cnt를 구한 이유가 여기서 나온다. 01111에 더해준 1000은 2^3 = 2^(cnt-1)이다. 즉 x가 홀수 일때 조건에 만족하는 수는 x + 2^(cnt-1)이다. 다른 수에 대해서도 계산을 해보면 조건을 충족한다.

 

class Solution {
    public long[] solution(long[] numbers) {
        long[] answer = new long[numbers.length];
        
        // 짝수인 경우 -> num + 1;
        // 홀수인 경우 -> num + 2 ^ ((1의 개수) - 1);
        
        for (int i = 0; i < numbers.length; i++) {
            // 짝수
            if (numbers[i] % 2 == 0) {
                answer[i] = numbers[i] + 1;
            } 
            // 홀수
            else {
                long tmp = numbers[i];
                long bit = 1;
                int cnt = 0;
                // 연속된 1 찾기
                while (tmp > 0) {
                    if (tmp % 2 == 1) cnt++;
                    else break;
                    tmp /= 2;
                }
                
                for (int j = 0; j < cnt - 1; j++) {
                    bit *= 2;
                }
                
                answer[i] = numbers[i] + bit;
            }
        }
        
        return answer;
    }
}

'Algorithm > Programmers' 카테고리의 다른 글

[Java] 선입 선출 스케줄링  (0) 2023.08.30
[Java] n^2 배열 자르기  (0) 2023.05.22
[Java] 조이스틱  (0) 2023.04.28
[Java] 주식가격  (0) 2023.04.25
[Java] 단체사진 찍기  (0) 2023.04.14