문제 링크

요약

  • 다음에 다시 풀어보기

최종

  • 이거 말고는 생각이 안나서 정답 봤음.
  • Stack 을 하나 두고 이 안에는 ‘항상’ index 가 오름차순으로 쌓이게 하며 lexicographic 적으로도 최소가 되게 하는 풀이를 생각해 보자.
  • 어차피 나중에 다시 한번 풀어볼거니까 자세한 코드 설명은 생략.
class Solution {
public:
	string smallestSubsequence(string s) {
		int in_stack_bms = 0;
		vector<int> rem('z' - 'a' + 1, 0);
 
		for (char c : s) {
			rem[c - 'a']++;
		}
 
		string stk;
		for (char c : s) {
			if (stk.empty()) {
				stk += c;
				in_stack_bms |= (1 << (c - 'a'));
			} else {
				if (!((in_stack_bms >> (c - 'a')) & 0x1)) {
					if (stk.back() < c) {
						stk += c;
						in_stack_bms |= (1 << (c - 'a'));
					} else if (stk.back() > c) {
						char t = stk.back();
 
						while ((t > c) && (0 < rem[t - 'a'])) {
							stk.pop_back();
							in_stack_bms ^= (1 << (t - 'a'));
 
							if (stk.empty()) {
								break;
							}
 
							t = stk.back();
						}
 
						stk += c;
						in_stack_bms |= (1 << (c - 'a'));
					}
				}
			}
			rem[c - 'a']--;
		}
 
		return stk;
	}
};

다른 풀이

Skip list

  • 다음으로 결과에 추가할 character 를 선택할 때
    • 우선 alphabet 순서로 가장 작고
    • 아직 추가되지 않은 character 이며
    • 지금까지 추가한 character set 과 해당 character 이후에 등장할 character set 의 합집합이 전체 집합이냐
  • 를 고려해서 선택해 나가는 방법이다.
  • 이를 위해서
    • 다음에 등장할 alphabet 이 어느 index 에 있는지 skip list 마냥 바로 찾아갈 수 있게 하고
    • 한 character 에 대해 이후에 등장하는 character set 들을 저장해놓는 방식
  • 설명이 좀 장황한데, 어차피 속도도 느리고 메모리도 많이 차지해서 별로 좋은 풀이는 아니어서 쉽게 풀어서 설명하지 않고 이정도까지만.