문제
https://programmers.co.kr/learn/courses/30/lessons/42883?language=python3
풀이
from itertools import combinations
def solution(number, k):
lst = list(combinations(range(len(number)), len(number)-k))
answer = []
for l in lst :
answer.append("".join([number[i] for i in l]))
return str(max(answer))
최초 접근한 방법. combinations를 통해 모든 조합을 구한 다음
거기서 최대값을 반환!! 결과는!!!
테스트 1 〉 통과 (0.20ms, 10.1MB)
테스트 2 〉 통과 (3320.16ms, 642MB)
테스트 3 〉 실패 (시간 초과)
테스트 4 〉 실패 (시간 초과)
테스트 5 〉 실패 (시간 초과)
테스트 6 〉 실패 (시간 초과)
테스트 7 〉 실패 (시간 초과)
테스트 8 〉 실패 (시간 초과)
테스트 9 〉 실패 (시간 초과)
테스트 10 〉 실패 (시간 초과)
테스트 11 〉 통과 (0.01ms, 10.2MB)
테스트 12 〉 통과 (0.01ms, 10.2MB)
그럼 그렇지. 다른 방법으로 접근해보자.
“가장 큰 수를 만드는 쉬운 방법”은 맨 앞자리수에
최대한 큰 수를 배치시키는 것이다.
즉, 앞 쪽에 최대한 큰 수가 올 수 있도록 해야한다.
이걸 신경써서 코드를 작성해봤다.
def solution(number, k):
number = list(number)
a = k
while k > 0 :
for i in range(len(number)-1) :
if number[i] < number[i+1] :
number.pop(i)
k -= 1
break
return "".join(number)
맨 앞자리부터 탐색을 하다가, 바로 다음 값이 지금 값보다 크면
무조건 pop 시키고 다시 첫자리부터 탐색을 진행한다.
이렇게 하면 Greedy 알고리즘 느낌이 살짝 난다.
테스트 1 〉 통과 (0.01ms, 10.1MB)
테스트 2 〉 통과 (0.01ms, 10.3MB)
테스트 3 〉 통과 (0.08ms, 10.1MB)
테스트 4 〉 통과 (0.21ms, 10.2MB)
테스트 5 〉 통과 (1.57ms, 10.2MB)
테스트 6 〉 통과 (344.32ms, 10.3MB)
테스트 7 〉 통과 (816.97ms, 10.6MB)
테스트 8 〉 통과 (8557.32ms, 11.1MB)
테스트 9 〉 통과 (52.82ms, 13MB)
테스트 10 〉 실패 (시간 초과)
테스트 11 〉 통과 (0.01ms, 10MB)
테스트 12 〉 실패 (시간 초과)
그러나 결과는 여전히 실패였다.
접근 방법은 맞았으나, 문자열의 길이가 길어지면 오버헤드가 너무 큰 것 같다.
저 동작을 축약시킬 방법이 없을까 곰곰히 생각해보니, 스택과 비슷했다.
아하! 스택 반환으로 다시 접근해보자.
def solution(number, k):
stack = []
for num in number :
while len(stack) > 0 and k > 0 and stack[-1] < num :
stack.pop()
k -= 1
stack.append(num)
return "".join(stack)
테스트 1 〉 통과 (0.01ms, 10.1MB)
테스트 2 〉 통과 (0.01ms, 10.3MB)
테스트 3 〉 통과 (0.04ms, 10.1MB)
테스트 4 〉 통과 (0.18ms, 10.2MB)
테스트 5 〉 통과 (0.37ms, 10.2MB)
테스트 6 〉 통과 (4.19ms, 10.4MB)
테스트 7 〉 통과 (9.90ms, 10.6MB)
테스트 8 〉 통과 (22.63ms, 10.8MB)
테스트 9 〉 통과 (38.53ms, 13.7MB)
테스트 10 〉 통과 (120.42ms, 13.3MB)
테스트 11 〉 통과 (0.01ms, 10.2MB)
테스트 12 〉 실패 (0.00ms, 10.2MB)
훠어어얼씬 빠르고 가볍다. 다만 마지막 케이스에 걸린다.
그런데 테스트케이스 12에서 아예 오답으로 나온다.
걸릴 수 있는 경우에 수가 뭐가 있나 찾아보니, 해당될 만한 부분이 있었다.
number = "1000", k = 2
이 경우 내 코드에서 “1000”이 그대로 출력되게 된다.
반복문을 다 수행하고도 여전히 길이가 안줄이든 경우를 추가하자.
def solution(number, k):
ok = len(number) - k
stack = []
for num in number :
while len(stack) > 0 and k > 0 and stack[-1] < num :
stack.pop()
k -= 1
stack.append(num)
while len(stack) > ok:
stack.pop()
return "".join(stack)
완성!! Level2 문제가 맞나 싶을 정도로 시간이 오래 걸렸다.
더 나은 풀이
def solution(number, k):
st = []
for i in range(len(number)):
while st and k > 0 and st[-1] < number[i]:
st.pop()
k -= 1
st.append(number[i])
return ''.join(st[:len(st) - k])
당혹스럽다. 특히 마지막 줄의 경우 충분히 생각해볼 수 있었는데
그저 “드디어 풀었다!” 라는 생각에 반복문을 한 바퀴 더 돌렸다.
다 완성해도 더 다듬을 수 있나 항상 고민하는 자세를 가져야겠다.
댓글남기기