탐욕법(Greedy)
큰 수 만들기
from itertools import combinations
def solution(number, k):
    answer = ''
    nums = []
    temp = []
    
    for i in range(len(number)): # number의 각 자리수를
        nums.append(number[i]) # nums 리스트에 추가해서
        
    combi = list(combinations(nums, len(number)-k)) # number의 길이에서 제거할 수의 개수인 k를 뺀만큼 조합을 구한다.
    
    for com in combi: # combi에 있는 조합된 수들을
        letter = ''
        for i in range(len(com)): 
            letter += com[i] # 문자 하나로 만들어준다. 
        temp.append(letter) # temp 배열에 문자를 추가해놓고
    
    return max(temp) # 가장 큰 수 찾기

테스트 케이스는 통과했는데 시간 초과 걸림 -> 절망ㅜ
combinations 함수가 너무 오래 걸리는건가 ..?
조합(combinations) 사용:
itertools.combinations를 사용하여 모든 가능한 조합을 생성하고, 각 조합을 문자열로 변환한 후 그 중 가장 큰 숫자를 선택하는 방식입니다.
조합의 수는 C(n, n-k)로 계산되며, n이 클수록 조합의 수가 급격히 증가합니다. 이는 시간 복잡도를 매우 크게 만듭니다. 예를 들어, number의 길이가 10이고 k가 5이면, 조합의 수는 C(10, 5) = 252가 됩니다. 길이가 100이라면 조합의 수는 훨씬 더 커져서 시간 초과가 발생합니다.
모든 조합을 탐색:
모든 가능한 조합을 생성하고 그 중 가장 큰 값을 찾는 방식은 비효율적입니다. 최악의 경우, 조합의 수가 매우 많아져 메모리와 시간 모두 비효율적입니다.
해결 방안:
이 문제는 스택을 사용하여 효율적으로 해결할 수 있습니다. 목표는 숫자를 왼쪽에서 오른쪽으로 탐색하면서 가능한 한 큰 수를 유지하는 것입니다.
def solution(number, k):
    stack = []
    for num in number:
        while stack and k > 0 and stack[-1] < num:
            stack.pop()  # 스택의 top에 있는 숫자가 현재 num보다 작으면 제거
            k -= 1
        stack.append(num)
    
    # 만약 k가 0보다 크다면, 끝에서 k개를 자른다.
    if k > 0:
        stack = stack[:-k]
    
    return ''.join(stack)
만약 k가 0보다 크다면, 끝에서 k개를 자른다. 여기 부분이 이해가 안가서 gpt한테 물어봤다. 
일곱 번째 숫자 1 처리:
stack = [7, 6, 5, 4, 3, 2]인데, stack의 top(2)이 현재 숫자 1보다 크므로 아무것도 제거하지 않고 1을 스택에 추가합니다.
stack = [7, 6, 5, 4, 3, 2, 1]
k = 3
남은 k 처리:
지금까지 숫자를 모두 순회했지만 k = 3이 남아 있습니다. 즉, 아직 3개의 숫자를 더 제거해야 합니다. 이 경우, 스택의 끝에서 k개의 숫자를 제거합니다. 이는 우리가 가능한 한 큰 숫자를 만들기 위해 뒤에서부터 작은 숫자를 제거하는 것입니다.
스택의 끝에서 3개의 숫자를 제거하면, 스택은 [7, 6, 5, 4]가 됩니다.
''.join(stack) : 리스트에 있는 문자열 요소들을 하나의 문자열로 합치는 방법import java.util.Stack;
class Solution {
    public String solution(String number, int k) {
        Stack<Character> stack = new Stack<>();
        
        // 모든 문자에 대해 반복
        for (int i = 0; i < number.length(); i++) {
            char num = number.charAt(i);
            
            // 스택의 top에 있는 숫자가 현재 num보다 작으면 제거
            while (!stack.isEmpty() && k > 0 && stack.peek() < num) {
                stack.pop();
                k--;
            }
            
            stack.push(num);
        }
        
        // 만약 k가 0보다 크다면, 스택의 끝에서 k개를 제거
        while (k > 0) {
            stack.pop();
            k--;
        }
        
        // 스택에 있는 문자들을 하나의 문자열로 합침
        StringBuilder answer = new StringBuilder();
        for (char num : stack) {
            answer.append(num);
        }
        
        return answer.toString();
    }
}
Stack 사용:
Stack를 사용하여 각 문자를 스택에 저장합니다.
반복문:
number의 각 문자를 반복하며 charAt(i)로 현재 문자를 가져옵니다. while 문에서 !stack.isEmpty()를 사용해 스택이 비어 있지 않은지 확인하고, stack.peek()으로 스택의 top에 있는 문자를 확인한 후 num과 비교하여 조건이 만족하면 pop()으로 제거합니다.
남은 k 처리:
스택을 모두 처리한 후에도 k가 남아있을 수 있으므로, 남아있는 k만큼 스택의 끝에서 문자를 제거합니다.
문자열 생성:
StringBuilder를 사용하여 스택에 있는 문자들을 하나의 문자열로 합칩니다. 이는 StringBuilder가 문자열을 효율적으로 조작할 수 있기 때문에 사용됩니다.
결과 반환:
최종적으로 answer.toString()을 호출하여 결과를 문자열로 반환합니다.
import java.util.Stack;
class Solution {
    public String solution(String number, int k) {
        char[] result = new char[number.length() - k];
        Stack<Character> stack = new Stack<>();
        for (int i=0; i<number.length(); i++) {
            char c = number.charAt(i);
            while (!stack.isEmpty() && stack.peek() < c && k-- > 0) {
                stack.pop();
            }
            stack.push(c);
        }
        for (int i=0; i<result.length; i++) {
            result[i] = stack.get(i);
        }
        return new String(result);
    }
}