문제 주소
https://www.acmicpc.net/problem/2812
문제 설명
N자리 숫자가 주어졌을 때, 여기서 숫자 K개를 지워서 얻을 수 있는 가장 큰 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 주어진다. (1 ≤ K < N ≤ 500,000)
둘째 줄에 N자리 숫자가 주어진다. 이 수는 0으로 시작하지 않는다.
출력
입력으로 주어진 숫자에서 K개를 지웠을 때 얻을 수 있는 가장 큰 수를 출력한다.
예제 입력 1
4 2
1924
예제 출력 1
94
예제 입력 2
7 3
1231234
예제 출력 2
3234
예제 입력 3
10 4
4177252841
예제 출력 3
775841
제출 코드 1
import java.io.*;
import java.util.*;
public class Main {
static char[] number;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
number = br.readLine().toCharArray();
int[] index = new int[N - K];
int largestIndex = -1;
int start = 0;
for (int i = 0; i < index.length; i++) {
int end = K + i;
largestIndex = findLargest(start, end, largestIndex);
index[i] = largestIndex;
start = largestIndex + 1;
}
StringBuilder sb = new StringBuilder();
for (int i : index) {
sb.append(number[i]);
}
System.out.println(sb);
}
static int findLargest(int start, int end, int prevLargestIndex) {
if (prevLargestIndex >= start) {
// 이전 최대인덱스가 탐색 범위 안에 없으면
for (int i = prevLargestIndex + 1; i <= end; i++) {
if (number[i] > number[prevLargestIndex]) {
prevLargestIndex = i;
}
}
return prevLargestIndex;
} else {
//처음부터 최대 인덱스를 찾는다
int largestIndex = start;
for (int i = start; i <= end; i++) {
if (number[i] > number[largestIndex]) {
largestIndex = i;
}
}
return largestIndex;
}
}
}
코드 1 설명
원래 이렇게 짰는데 시간이 초과되어서 시간을 줄일 수 있는 방법을 찾아보다가 저렇게 케이스 분리를 했다
import java.io.*;
import java.util.*;
public class Main {
static char[] number;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
number = br.readLine().toCharArray();
int[] index = new int[N - K];
int largestIndex = -1;
for (int i = 0; i < index.length; i++) {
largestIndex = findLargest(largestIndex + 1, K + i);
index[i] = largestIndex;
}
StringBuilder sb = new StringBuilder();
for (int i : index) {
sb.append(number[i]);
}
System.out.println(sb);
}
static int findLargest(int start, int end) {
int largestIndex = start;
for (int i = start; i <= end; i++) {
if (number[i] > number[largestIndex]) {
largestIndex = i;
}
}
return largestIndex;
}
}
뒤에서 N-K를 넘어가서 처음 것을 고르게 되면 차례대로 다 골라도 숫자가 모자라게 된다
그래서 앞에서부터 K + i (N-(N-K)+i)인곳까지 안에서만 숫자를 골라야 한다
그 중에서 가장 큰 것을 골라서 넣어주게 코드를 짰는데
자꾸 시간초과가 되어서 케이스 분리를 해서 조금 더 빠르게 해줬더니 통과했다
다른사람의 풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().split(" ");
int N = Integer.parseInt(input[0]);
int K = Integer.parseInt(input[1]);
String number = br.readLine();
System.out.println(findLargestNumber(N, K, number));
}
public static String findLargestNumber(int N, int K, String number) {
Stack<Character> stack = new Stack<>();
int toRemove = K;
for (int i = 0; i < N; i++) {
char current = number.charAt(i);
while (!stack.isEmpty() && toRemove > 0 && stack.peek() < current) {
stack.pop();
toRemove--;
}
stack.push(current);
}
// 만약 아직 지워야 할 숫자가 남아있는 경우 뒤에서부터 지움
while (toRemove > 0) {
stack.pop();
toRemove--;
}
// 스택의 내용을 문자열로 변환
StringBuilder sb = new StringBuilder();
for (char c : stack) {
sb.append(c);
}
return sb.toString();
}
}
풀이 설명
스택을 활용해서 풀었다 -> 이게 위보다 나은 풀이인것 같다...
숫자를 하나하나 보면서
스택이 비어있지 않고 제거해야할 숫자가 남아있으면 (toRemove>K)
그리고 스택의 맨 위 숫자가 현재 숫자보다 작으면
맨 위의 숫자를 제거해준다
숫자를 하나 줄였으니까 toRemove를 1 감소시킨다
현재 숫자를 스택에 추가한다
모든 숫자를 처리한 후에도 제거해야 할 숫자가 남아있다면 스택의 뒤쪽에서부터 숫자를 제거한다
'Coding Test' 카테고리의 다른 글
[백준] 다음 순열 (0) | 2024.06.21 |
---|---|
[프로그래머스] 가장 큰 정사각형 찾기 (0) | 2024.06.19 |
[프로그래머스] 124나라의 숫자 (0) | 2024.06.03 |
[프로그래머스] 파일명 정렬 (1) | 2024.06.03 |
[프로그래머스] 프렌즈4블록 (1) | 2024.06.03 |