프로그래머스 다음 큰 숫자
문제 바로가기
자연수 n이 주어졌을 때, n의 다음 큰 숫자는 다음과 같이 정의 합니다.
- 조건 1. n의 다음 큰 숫자는 n보다 큰 자연수 입니다.
- 조건 2. n의 다음 큰 숫자와 n은 2진수로 변환했을 때 1의 갯수가 같습니다.
- 조건 3. n의 다음 큰 숫자는 조건 1, 2를 만족하는 수 중 가장 작은 수 입니다.
예를 들어서 78(1001110)의 다음 큰 숫자는 83(1010011)입니다.
자연수 n이 매개변수로 주어질 때, n의 다음 큰 숫자를 return 하는 solution 함수를 완성해주세요.
제한 사항
- n은 1,000,000 이하의 자연수 입니다.
접근방식
문제를 보자마자 두 가지 방식이 떠올랐다.
- Bitset 사용하기
- 비트연산자 사용하기
뭔가 2번 으로 풀고싶어졌다.
조건에서 규칙을 찾아보자.
78(1001110)의 다음 큰 숫자는 83(1010011)이다. 두 수를 보면 오른쪽에서 4~5번째 순서에서 규칙을 찾을 수 있다.
즉, 1 다음에 처음으로 0이 나왔을때 1과 0 두 수를 바꿔주고 나머지 오른쪽에 있는 1들은 제일 오른쪽으로 이동시켜주면 되는것이다.
4번째와 5번째 수를 변경 (1010110) -> 나머지 1들은 맨 오른쪽으로 이동 (1010011)
숫자 15로도 해보자.
15(1111)의 다음 큰 숫자는 23(10111)이다.
4번째와 5번째 수를 변경 (10111) -> 나머지 1들을 맨 오른쪽으로 이동 (10111)
뭔가 설명이 안 와닿을수도 있다. 일단 이런 알고리즘으로 작동한다는걸 이해하고 코드로 구현해보자.
#include <stack>
using namespace std;
int solution(int n) {
int answer = n, num_of_one = 0,k = 1;
stack<int> a;
if(n & 1 == 1) num_of_one++;
a.push(n & 1);
n >>= 1;
while(1){
//1. n을 1과 &연산을 해주고 나온 숫자를 a라는 스택에 넣어준다. 연산결과가 1인경우 count센다.
//2. n을 1씩 오른쪽으로 비트 이동을 해준다.
//3. 스택의 top이 1이고 n의 제일 오른쪽 비트가 0일 때 멈춰준다.
if(n == 0) break;
if(a.top() == 1 && (n & 1) == 0) break;
else{
if((n & 1) == 1) num_of_one++;
a.push(n & 1);
n >>= 1;
}
}
answer |= (k << a.size()); //1 바로 다음의 0을 1로 바꿔준다.
for(int i = 0; i< a.size(); i++){
if(i < num_of_one-1) answer |= k;
//1개수 하나 빼주고 아래 1들을 제일 오른쪽으로 이동
else answer &= ~k;
//나머지는 0으로 바꿔준다
k <<= 1;
}
return answer;
}
Author And Source
이 문제에 관하여(프로그래머스 다음 큰 숫자), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@fufru/PRGRMS-다음-큰-숫자저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)