[Programmers] 큰 수 만들기

2 minute read

큰 수 만들기

문제 설명


문제 설명

어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 합니다.

예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있습니다. 이 중 가장 큰 숫자는 94 입니다.

문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어집니다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하세요.

제한 조건
  • number는 1자리 이상, 1,000,000자리 이하인 숫자입니다.
  • k는 1 이상 number의 자릿수 미만인 자연수입니다.
입출력 예
number k return
“1924” 2 “94”
“1231234” 3 “3234”
“4177252841” 4 “775841”

출처


문제 풀이


# 그리디 # 스택


같은 2단계 문제인(지난번에 포스팅한) ‘가장 큰 수’ 문제와 비슷한 점이 있는 것 같습니다.


사용하는 자료 구조나 알고리즘이 비슷한 것은 아니지만,

‘O(n^2^)의 완전 탐색으로는 통과할 수 없고, 규칙을 찾아 O(n) 의 시간 복잡도를 만들어야 한다’는 점에서 비슷하다고 생각합니다.

두 문제 모두 입력 길이가 각각 100,000과 1,000,000으로 십만이 이 정도의 길이를 갖는 문제에 대해서는 완전 탐색을 제쳐두고,

‘아, 문제에 만족하는 규칙을 찾아야 하는 문제구나’

라고 생각해도 무방할 것 같습니다.


이 문제는 주어진 숫자에서 k개의 자리를 제외하여, 가장 큰 수를 찾는 문제입니다.

숫자에서 가장 큰 수를 찾는 것이라면 자연스럽게 높은 자릿수 숫자가 커야한다가 떠올라야 겠죠!


우선, 먼저 실패한 코드입니다.

def solution(number, k):
  for _ in range(k):
    number = sorted([number[:i]+number[i+1:] for i in range(len(number))])[-1]
  return number

각 자릿수를 제외한 숫자들 중 가장 큰 수를 찾아 풀어보려 했지만 … O(n^2)의 시간 복잡도로 성공할리가 없죠.


따라서 우리는 스택을 사용해야 합니다.

스택은 때때로 문제 풀이의 시간 복잡도를 O(n)으로 만들어주는 아주 좋은 자료구조입니다.

예를 들면, [Programmers] 주식 가격 문제 또한 그렇습니다.

🔥수열에 있어 정해진 대소 관계(또는 순서 관계)를 따라야 할 때, 스택을 사용할 수 있습니다. 🔥

def solution(number, k):
    s = []
    for i in range(len(number)):
        while s and s[-1] < number[i]: 
            s.pop()
            k -= 1
            if k == 0: return ''.join(s + list(number[i:]))
        s.append(number[i])
    return ''.join(s)[:-k]

앞자릿수가 더 커야 한다는 규칙을 이용하여, 스택의 맨 뒤 원소가 이번에 push할 원소보다 작다면 맨 뒤 원소가 push할 원소보다 크거나 스택이 빌 때까지 원소를 pop합니다.

number의 각 자릿수를 모두 돌지 않더라도, k번의 pop이 이루어졌으면 스택 원소에 돌지 않은 자릿수들을 붙여서 반환합니다.

반대로 각 자릿수를 모두 돌았는데도 k번의 pop이 이루어지지 않았으면 k개의 스택의 뒤쪽 원소(낮은 자릿수)를 제외하고 반환합니다.


간단히 예시를 들어 설명하면 다음과 같습니다.

  • number = “4177252841”, k=4

    k(pop할 횟수) s(스택) 연산
    4 [4] append
    4 [4, 1] append
    3 [4] pop
    2 [] pop
    2 [7] append
    2 [7, 7] append
    2 [7, 7, 2] append
    1 [7, 7] pop
    1 [7, 7, 5] append
    1 [7, 7, 5, 2] append
    0 [7, 7, 5] push
    0 [7, 7, 5, 8] append

    return “775841”


  • number = “999”, k=2

    k s 연산
    2 [9] append
    2 [9, 9] append
    2 [9, 9, 9] append

    return “9”

Leave a comment