LeetCode - Remove Duplicate Letters (Javascript)
문제 설명
릿코드 문제를 풀면서 처음으로 문제가 이해가 되지 않았었다..
주어진 문자열 내에서 모든 문자를 딱 한 번씩만 사용하여 나열하되, 주어진 순서 내에서 문자열이 최대한 오름차순으로 정렬될 수 있도록 해야 한다. 즉, ‘cbacdcbc’가 주어졌다고 가정했을 때, acdb가 도출될 것이다. 왜냐하면 a 다음에 올 수 있는 문자는 b,c,d인데 b가 a 다음에 와버리면 d가 들어갈 수 있는 자리가 없어진다. 따라서 ac → acd → acdb의 과정을 통해 acdb가 최종적으로 반환되어야 한다.
Given a string s
, remove duplicate letters so that every letter appears once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.
Example 1:
1 | Input: s = "bcabc" |
Example 2:
1 | Input: s = "cbacdcbc" |
Constraints:
1 <= s.length <= 104
s
consists of lowercase English letters.
소스 코드 (1차 시도)
역시나 통과는 됐지만 시간복잡도가 처참하다ㅜ
1 | function removeDuplicateLetters(s) { |
소스코드 (최종)
너무 허무하다…
딱 코드 한 줄 추가했을 뿐인데 시간복잡도가 대폭 상승했다.
1 | function removeDuplicateLetters(s) { |
풀이 설명
기본적으로 Stack을 사용했다.
그리고 방문 여부를 판별할visited
와, 문자의 개수를 담을count
객체를 활용했다.
먼저, 아래와 같은 스택과, ‘acdcbc’ 문자열이 주어졌다고 가정해보자.
그러면 a는 기본적으로
stack
에push
된다.
그리고 그 뒤로는 계속 c,d가 연속으로 들어올 수 있다. a가 가장 작고, c는 d보다 작기 때문이다.
그리고 그 다음번에는 또 다시 c가 나오는데, stack
에 문자가 push
될 때마다 visited
에 해당 요소의 사용 여부가 등록되기 때문에, c는 그냥 지나쳐 간다.
중요한 포인트가 위의 예시에서 등장한다.
d는 b보다 크기 때문에
while
문에 의해 b보다 큰 값들이 사라질 때까지stack.pop()
이 실행돼야 하기 때문이다.
하지만, 조건문 내에 문자의 남은 개수가 0이라면 while
문이 실행되지 않도록 방어 조건문을 추가해 두었다. 따라서 남은 d의 개수는 0이기 때문에, stack
의 요소 제거 없이 b가 그대로 push
된다.
그리고 최종적으로 c는 visited
가 true
이기 때문에 무시되며 모든 반복문이 종료되고 stack
에 들어가 있는 문자들이 차례대로 join(’’)
에 의해 합쳐져 반환되는 것이다.
LeetCode - Remove Duplicate Letters (Javascript)
https://hoonjoo-park.github.io/algorithm/leet/removeDupLetters/