2023. 2. 14. 12:17ㆍCS/자료구조 & 알고리즘
문제 출처
[프로그래머스 코딩 테스트 연습]
https://school.programmers.co.kr/learn/courses/30/lessons/12911
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이
이 문제는 다음과 형태로 진행이 된다.
예시는 1001110을 예시를 든다.
- 가장 오른쪽에 있는 1을 구하기
ex) 1001110 → 0000010 - 1번 왼쪽에서 가까운 0비트에 1비트로 바꾸고 나머지 자르기
ex) 1001110 → 1010000 - 비트수 맞추기
ex) 1010000 → 1010011

1. 가장 오른쪽에 있는 1을 구하기
1001110에서 가장 오른쪽 비트를 가져오는 방법이 무엇일까?
일단 and 연산에 대해 알아보자.
and 연산은 서로 같으면 1 다르면 0이 되는 비트연산이다.
and 연산을 사용한다면 가장 오른쪽에 있는 1을 구하려면 가장 오른쪽 1을 제외하고 전부 달라야 된다.
즉 0110010이 되어야 한다.
0110001에서 +1을 하면 된다.
여기서 더 나아가면 0110001은 원래 비트의 1의 보수이다.
그리고 2의 보수는 1의 보수에서 +1을 하면 되고 이는 컴퓨터에서 음수를 표현하는 방법 중하나이다.
즉 Java에서도 -int를 하면 2의 보수로 저장이 된다.
정리하면 다음과 같다.
1001110의 1의 보수를 구하면 0110001이 된다.
여기서 1을 더하면 0110010이 된다. - - - - - (1)
(1) 번 비트와 원래 비트를 and 연산하면 가장 오른쪽에 있는 1비트를 구할 수 있다.
그리고 (1) 번 비트는 컴퓨터와 java에서 음수를 표현하는 방법이다.
and 연산이란 각 비트를 비교했을때 같으면 1, 다르면 0이 되는 연산이다.
1001110 and 0110010 0000010
이와 같이 0000010 가장 오른쪽에 있는 비트를 얻어 낼 수 있다.
n & -n
2. 1번 왼쪽에서 가꾸운 0비트에 1비트로 바꾸고 나머지 자르기
그림에서는 바꾸기 다음에 자르기로 했지만 사실상 1번에서 얻은 비트를 원래 비트랑 더하면 된다.
더하면 자릿수가 바뀌게 되면서 나머지가 잘라지게 된다.

n = n + (n & -n);
3. 비트수 맞추기
비트 수를 맞추려면 추가해야 하는 비트를 추가해 주면 된다.
추가해야 할 비트 수를 알려면 자르기 전후의 비트 수의 차를 구하면 된다.
자바에서 비트의 수를 얻으려면 Integer.bitCount(int)을 사용하면 된다.
int bitCount = Integer.bitCount(n); n = n + (n & -n); int bitCount2 = Integer.bitCount(n);
오른쪽에서부터 n개의 비트를 추가하는 방법을 알아보자.
0000001을 10진수로 변환하면 1이다
0000011을 10진수로 변환하면 3이다
0000111을 10진수로 변환하면 7이다
0001111을 10진수로 변환하면 15이다
1, 3, 7, 15는 (2^ n) - 1식으로 올라가고 있다. (n은 비트수)
즉 n에 비트의 차를 넣고 2번에서 얻은 n에 더하면 된다.
n += Math.pow(2, bitCount - bitCount2) - 1;
소스 코드
public class Solution { public int solution(int n) { int bitCount = Integer.bitCount(n); n = n + (n & -n); int bitCount2 = Integer.bitCount(n); n += Math.pow(2, bitCount - bitCount2) - 1; return n; } }
'CS > 자료구조 & 알고리즘' 카테고리의 다른 글
[Programmers] Lv2 영어 끝말잇기 Java (0) | 2023.02.16 |
---|---|
[Programmers] Lv2 짝지어 제거하기 Java (0) | 2023.02.15 |
[Programmers] Lv2 빛의 경로 사이클 Java (0) | 2023.02.11 |
[Programmers] Lv1 문자열 나누기 Java (0) | 2023.02.07 |
[Programmers] Lv1 성격 유형 검사하기 Java (0) | 2023.02.06 |