본문 바로가기
algorithm/leetcode

Remove K Digits [leetcode]

by hoonzii 2022. 2. 19.
반응형

문제링크

 

문제 풀이

Input: num = "1432219", k = 3
Output: "1219"

첫번째 풀이

처음에는 앞 숫자와 뒤 숫자를 비교해서 뒤 숫자가 크면 해당 숫자를 지우는 로직인줄 알았다.

그럼 위 예시로 보면

1 : “4” 32219→ 4가 크므로 4를 지운다 ⇒ 132219 (k =2)

1 : “3” 2219→ 3이 크므로 3을 지운다 ⇒ 12219 (k=1)

1 : “2” 219→ 2가 크므로 2를 지운다 ⇒ 1219 (k=0 이므로 종료)

그럼 정답으로 1219 이므로 쉽게 푼줄 알았다.

 

하지만 반례로

Input: num = "12345", k = 2
Output: "123"

위 반례가 있다.

1 : 2 → 2가 크므로 2를 지운다 ⇒ 1345 (k=1)

1 : 3 → 3이 크므로 3을 지운다 ⇒ 145 (k=0 이므로 종료)

정답인 123 과 다르다...

 

 

2번째 풀이

그렇다면 앞 숫자와 뒤 숫자를 비교했을때 앞 숫자가 크면 지우게끔 만들고,

12345 같이 앞숫자가 계속 작았다면! (k가 지워진게 없을테니)

남은 만큼 뒤에서 부터 지우면 되지 않을까?

그럼 12345 의 경우에는 k=2인 채로 loop 가 끝날테니 loop 끝나고 뒤에 두자리를 지우면 123이 나올터였다.

 

 

하지만 반례로...

Input: num = "1234567890", k = 9
Output: "0"

k가 지워지는 유일한 구간은. 9 : 0 비교시 9를 지울때 뿐이다. (k=8)

그럼 123456780 에서 뒤에서 부터 지울테니 답은 1이 나오게 된다...

 

 

3번째 풀이

자 그렇다면 앞 숫자와 뒤 숫자를 비교할때 뒤 숫자가 작다면 계속 비교해서 지우면 안될까?

12345678 9 : 0 이면 9 지우고 (k=8)

1234567 8 : 0 이면 8 지우고

123456 7 : 0 이면 7 지우고

12345 6 : 0 이면 6 지우고

.

.

이런식으로 한번 비교로 끝나는게 아니라 0 자리에 왔을때 계속해서 지워나가면 어떨까?

코드로 보자 (list의 변수 이름을 stack으로 한건 마지막 자리를 비교하고 넣고 빼는거 같아서...)

if stack[-1] > n: # 9 > 0 이면
  while len(stack) > 0 and k > 0: # 스택이 비어있지 않고, K값이 0보다 클때
      last = stack.pop() # 마지막 숫자 pop
      if last > n: # 마지막 숫자가 0보다 크기 때문에
          k -= 1 # k-1 해준다 (pop으로 이미 스택에서는 빠졌다)
      else: # 마지막 숫자가 크다면
          stack.append(last) #pop했던 숫자를 원복해주고 루프를 빠져나온다.
          break 
  stack.append(n) # 못넣었던 숫자를 넣어준다.

 

이 작업을 통해서도 K가 0이 되지 않았다면 위 2번째 풀이 에서 진행했던 마지막 숫자들을 지워줄 필요가 있다.

(앞 숫자보다 뒤 숫자가 더 크기 때문에 위 로직을 타지 않는다.)

if k != 0:
  while k != 0:
      last = stack.pop() # 마지막 숫자 
      prev = stack.pop() # 마지막 이전 숫자 
      if last < prev: # 둘을 비교해서 작은 숫자만 스택에 넣어준다.
          stack.append(last)
      else:
          stack.append(prev)
      k -= 1 # 해당 작업시 마다 k값은 하나씩 사라짐

 

또 주의 점이 있다.

“01” 은 “1” 로 변경되어야 한다. (숫자의 맨앞은 0이 오면 안되므로)

first = stack[0]
while first == "0":
    stack.pop(0)
    if len(stack) > 0:
        first = stack[0]
    else:
        break

 

위 작업이 끝났을때 스택이 비어 있다면 “0” 으로 치환하라고 문제에 써 있으므로

result = ""
if len(stack) == 0:
    return "0"
else:
    result = "".join(stack)

결과는

이번 코드는 내가 봐도 좀 더럽다...

전체코드

class Solution:
    def removeKdigits(self, num: str, k: int) -> str:
        if len(num) == k:
            return "0"
        
        stack = []
        for n in num:
            if len(stack) == 0:
                stack.append(n)
            else:
                if k == 0:
                    stack.append(n)
                else:
                    if stack[-1] > n:
                        while len(stack) > 0 and k > 0:
                            last = stack.pop()
                            if last > n:
                                k -= 1
                            else:
                                stack.append(last)
                                break
                        stack.append(n)
                    else:
                        stack.append(n)
        
        if k != 0:
            while k != 0:
                last = stack.pop()
                prev = stack.pop()
                if last < prev:
                    stack.append(last)
                else:
                    stack.append(prev)
                k -= 1
                
        first = stack[0]
        while first == "0":
            stack.pop(0)
            if len(stack) > 0:
                first = stack[0]
            else:
                break
        
        result = ""
        if len(stack) == 0:
            return "0"
        else:
            result = "".join(stack)
        
        return result

 

 

반응형

'algorithm > leetcode' 카테고리의 다른 글

Linked List Cycle [leetcode]  (0) 2022.03.09
Arithmetic Slices [leetcode]  (0) 2022.03.03
Swap Nodes in Pairs [leetcode]  (0) 2022.02.16
Subsets [leetcode]  (0) 2022.02.13
Permutation in String [leetcode]  (0) 2022.02.11

댓글