[C++] BOJ #2812 크게 만들기
Posted on 2022. 02. 24
문제
N자리 숫자가 주어졌을 때, 여기서 숫자 K개를 지워서 얻을 수 있는 가장 큰 수를 구하는 프로그램을 작성하시오.
입력
-
첫째 줄에 N과 K가 주어진다. (1 ≤ K < N ≤ 500,000)
-
둘째 줄에 N자리 숫자가 주어진다. 이 수는 0으로 시작하지 않는다.
출력
- 입력으로 주어진 숫자에서 K개를 지웠을 때 얻을 수 있는 가장 큰 수를 출력한다.
1. 해결방법 및 소스코드
- 큐(Queue)와 스택(Stack)을 활용하였다.
- 우선, N이 최대 500,000인데 5십만자리 수는 기본적인 자료형으로 표현할 수 없으므로 수를 문자열로 받는다.
char
형으로 받은 수를x
라고 하면x-'0'
으로 정수로 변환할 수 있으므로 변환한 정수를 큐에 넣는다. - 최종적으로 다룰 결과는 result라는 스택에서 완성된다. result스택에 우리가 받은 수(큐)에서 가장 앞자리수
(number.front()
)를 추출(pop
)하여 스택에 쌓음으로서 본격적인 풀이를 할 준비가 완료된다.
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
int main()
{
int N, K;
int resultsize;
stack<int> result;
queue<int> number;
scanf("%d %d", &N, &K);
char numstring[N + 1];
scanf("%s", numstring);
int print_result[N];
for (int i = 0; i < N; i++)
{
number.push(numstring[i] - '0');
}
//스택에 N자리 숫자의 맨 앞자리를 넣어주며 시작
result.push(number.front());
number.pop();
- 큐에서 한 번 pop을 해주었기 때문에 큐의 맨 앞에는 N자리 숫자의 두번째 숫자가 와 있다.
- 이제 number 큐에서 하나씩 pop을 해주면서 큐가 empty될 때까지 아래의 연산을 반복하면 된다.
number.front() > result.top()
인 경우에는 result 스택에서number.front()
보다 작은 값이 없을 때까지 result 스택을 pop해준다. 당연히 pop 한번에 K도 하나씩 감소시킨다. 이 때 반복적인 pop의 조건은 result스택이 비어있으면 안되고, K > 0임이 함께 보장되어야한다.- 위 1번 조건에 만족하지 않거나 1번 조건에서의 반복적인 pop을 마무리해준 후, 그때서야
number.front()
를 result 스택에 push 할 수 있게된다. - 위 1, 2번 조건을 모두 마쳤으나 K가 아직 남아있을 수 있다. 이럴 경우에는 남은 K만큼 result 스택을 pop 해주고 K를 완전 소모시킨다.
// N자리 숫자의 2번째자리 숫자부터 검사 시작
while (!number.empty())
{
int numberfront = number.front();
// printf("numberfront: %d\n", numberfront);
if (numberfront > result.top())
{
while (!result.empty() && (numberfront > result.top()) && K > 0)
{
// printf("%d를 pop합니다!\n", result.top());
result.pop();
K--;
}
}
// printf("%d를 push합니다!\n", numberfront);
result.push(numberfront);
number.pop();
}
//그럼에도 남은 K가 있다면 싹다 정리
while (K > 0)
{
result.pop();
K--;
}
- 이제 result 스택의 사이즈를 알아낸 후, result 스택에서 남아있는 결과값을 프린트 해 줄
print_result
배열에 result 스택의 수를 옮겨담고, 결과를 출력한다.
resultsize = result.size();
for (int i = result.size() - 1; i >= 0; i--)
{
// printf("인덱스 %d 에 %d 저장\n", i, result.top());
print_result[i] = result.top();
result.pop();
}
for (int i = 0; i < resultsize; i++)
{
printf("%d", print_result[i]);
}
printf("\n");
}
2. 전체 소스코드
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
int main()
{
int N, K;
int resultsize;
stack<int> result;
queue<int> number;
scanf("%d %d", &N, &K);
char numstring[N + 1];
scanf("%s", numstring);
int print_result[N];
for (int i = 0; i < N; i++)
{
number.push(numstring[i] - '0');
}
//스택에 N자리 숫자의 맨 앞자리를 넣어주며 시작
result.push(number.front());
number.pop();
// N자리 숫자의 2번째자리 숫자부터 검사 시작
while (!number.empty())
{
int numberfront = number.front();
// printf("numberfront: %d\n", numberfront);
if (numberfront > result.top())
{
while (!result.empty() && (numberfront > result.top()) && K > 0)
{
// printf("%d를 pop합니다!\n", result.top());
result.pop();
K--;
}
}
// printf("%d를 push합니다!\n", numberfront);
result.push(numberfront);
number.pop();
}
//그럼에도 남은 K가 있다면 싹다 정리
while (K > 0)
{
result.pop();
K--;
}
resultsize = result.size();
for (int i = result.size() - 1; i >= 0; i--)
{
// printf("인덱스 %d 에 %d 저장\n", i, result.top());
print_result[i] = result.top();
result.pop();
}
for (int i = 0; i < resultsize; i++)
{
printf("%d", print_result[i]);
}
printf("\n");
}