[프로그래머스-Greedy] 큰 수 만들기

CHOI YUN HO·2021년 1월 25일
1

알고리즘 문제풀이

목록 보기
6/63

📃 문제 설명

큰 수 만들기

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

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

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

제한사항

  • number는 1자리 이상, 1,000,000자리 이하인 숫자입니다.
  • k는 1 이상 number의 자릿수 미만인 자연수입니다.

입출력 예

numberkreturn
"1924"2"94"
"1231234"3"3234"
"4177252841"4"775841"

[문제 출처 : 프로그래머스]

👨‍💻 해결 방법

나의 생각의 흐름을 주절주절..

주어진 문자들의 위치를 바꾸지 않고 그 자리에서 삭제만 시켜서(?)
가장 큰 수를 만들어야 하기 때문에
큰 자릿수에 가장 큰값이 오도록 해봤다.

주어진 문자열의 처음부터 인접해있는 문자들을 비교하여
앞 문자가 더 작으면 삭제한다.

그러니까 "1924", k=2 의 경우
"1"을 삭제하고 "924"가 된다
"2"를 삭제하고 "94"가 된다.
삭제를 두 번 했으므로 끝! (k=2)

그런데 number[i]와 number[i+1]을 비교하는 방식으로 풀었더니 시간 초과가 발생했다.

삭제를 진행하고나서 삭제된 후의 문자열을 다시
처음부터 비교하기 때문에 불필요한 비교가 많이 생기기 때문인 것 같다.

예를 들어, "41777725" 같은 문자열이 있을 때
1과 4가 삭제된 후 "777725"가 됐을 때 앞자리는 더이상 비교가 필요 없는데 위와 같은 방법으로 풀면 계속 비교가 진행된다. 문자열이 매우 긴 경우 더 심각하겠지
(99999...뭐 이런 식이면....)

그래서 스택을 사용하여 풀어보았다.

문자열을 앞에서부터 하나씩 스택에 넣어주는데
넣을 문자가 스택의 top보다 크면
스택에서 pop을 수행하고 k를 1 빼준다.
이 과정을 k가 0이 될 때까지 수행해주는 것이다.
이렇게하면 불필요한 비교를 줄일 수 있다.

결론

문자열의 앞에서부터 하나씩 스택에 넣어주는데,
넣을 문자가 스택의 top보다 크면 pop을 수행한다.

그러면 문자열의 앞에서부터 큰값만 차례대로 스택에 쌓이게 되고
k가 0이면 삭제할 횟수를 다 채운 것이므로 그대로 스택의 값들을 문자열로 변환하여 반환해주면 된다.

다만, k가 0보다 클 경우 문자열을 다 돌았는데도 삭제할 횟수가 남은 것이므로,
이 때는 뒤에서 k개 만큼 삭제하면 된다.
어차피 자릿수는 그대로인 상태로 삭제해서 큰 수를 만들어야 하니까~

시간 초과를 해결하기 위해 고민해보는게 재미있었다.

👨‍💻 소스 코드

def solution(number, k):
    answerList = []

    for i in range(len(number) - 1):
        answerList.append(number[i])
        i += 1
        while len(answerList) > 0 and number[i] > answerList[-1] and k > 0:
            answerList.pop()
            k -= 1
    answerList.append(number[-1])

    if k > 0:
        answerList = answerList[:-k]

    return "".join(answerList)
profile
가재같은 사람

0개의 댓글