민규의 흔적

[Python 파이썬] 프로그래머스 - 큰 수 만들기 본문

프로그래머스

[Python 파이썬] 프로그래머스 - 큰 수 만들기

민규링 2024. 6. 10. 19:41

2024년 6월 10일

문제 링크 : 프로그래머스 - 큰 수 만들기

 


문제 접근

 

주어진 숫자 number에서 k개의 수를 제거하여 도출될 수 있는 가장 큰 수를 구하면 된다.

 

이는 아주 그리디하게 접근 가능하다.

최대한 큰 수가 앞자리 수에 오도록 유도하는 것이다.

이에 나는 스택 구조를 활용하여, 최대한 앞자리에 오는 작은 수를 먼저 없애는 것에 초점을 두었다.

 

1924를 예로 보자.

 

 

k는 2이고, 가장 첫 번째 자리수는 1이다.

stack이 비어있기에 비교할 대상이 없어 now를 append 해준다.

 

 

now는 9이고, stack의 마지막 요소는 1이기에 맨 앞 자리수에 1보단 9가 오는게 수가 더 클 것이다.

이에 stack의 마지막 요소가 now보다 크거나 같은 값일 때까지 pop 하며 k를 1씩 감소시킨다.

이후 now를 stack에 append해준다.

 

 

now는 2이고, stack의 마지막 요소는 9다. 2보다 9가 더 크기에 stack에 append 해준다.

 

 

now는 4이고, stack의 마지막 요소는 2이다. 해당 자리수에는 2보다 4가 오는게 더 수가 클 수 있고, 아직 삭제 횟수가 남아있기에 stack의 마지막 요소를 pop 해주고 now를 append 한다.

 

 

k = 0으로 더 이상 삭제할 수 없고, 주어진 숫자의 모든 자리수를 확인해 보았다.

따라서, 1924에서 수 2개를 삭제하여 나타낼 수 있는 가장 큰 수는 94이다.

 

다른 예시도 보자.

 

number = 4177252841

 

 

 

모든 자리수가 같은 수인 경우는 어떨까?

 

number = 22222

 

 

로직대로라면 stack의 마지막 요소보다 now가 클 경우에면 pop 해주므로, 위 과정에서 pop되는 과정은 없다.

하지만 k개를 무조건 삭제해야 하기 때문에 최종 stack에서 k번 만큼 pop 해주어야 한다.

왜 마지막 요소부터 삭제해야 하는가? 다음과 같은 경우 때문이다.

 

 

위 수는 앞 자리수보다 뒷 자리수가 작아지는 내림차순 형태이기 때문에, 22222 처럼 최종 stack까지 하나도 pop되지 않고 그대로 append 될 것이다.

하지만 무조건 k개를 삭제해야 한다. 앞자리 수가 무조건 더 크기 때문에, 맨 뒷자리 수부터 삭제해야 하므로 맨 뒷자리 수를 k번 pop해주는 것이 무조건 큰 수가 될 수 있다.

 


전체 코드

 

def solution(number, k):
    stack = []
    for i in range(len(number)):
        while stack and k > 0 and stack[-1] < number[i]:
            stack.pop()
            k -= 1

        stack.append(number[i])

    while k > 0:
        stack.pop()
        k -= 1

    return "".join(stack)

if __name__ == "__main__":
    number = "4177252841"
    k = 4

    print(solution(number, k))

풀이 후기

 

그리디하게 접근하고 시간복잡도를 챙기기 위해 스택 자료구조를 활용해 효율적으로 문제를 풀려고 노력했다.

이런 문제가 그리디 알고리즘 유형의 정석이라고 생각한다.