316. Remove Duplicate Letters

  • μ „ν˜€ 감이 μ•ˆ μ™€μ„œ λͺ» ν’€μ—ˆλ˜ 문제. κ²°κ΅­ 해닡을 λ΄€λ‹€.
    • Greedyν•˜κ²Œ 닡을 λ§Œλ“€μ–΄λ³΄λ €κ³  ν–ˆλŠ”λ° κ·œμΉ™μ„ μ„Έμš°κΈ°κ°€ 쉽지 μ•Šμ•˜λ‹€.
    • κ²°κ΅­ 이미 κ²°κ³Ό result 에 λ“€μ–΄κ°€ μžˆλŠ” 것을 상황에 따라 μˆ˜μ •ν•˜λŠ” 방식을 μ·¨ν–ˆμ–΄μ•Ό ν–ˆλ‹€.
  • λ¬Έμžμ—΄μ„ 순회 ν•˜λ©΄μ„œ κ²°κ³Ό result 에 ν•˜λ‚˜μ”© λ„£κ³  ν•΄λ‹Ή 문자λ₯Ό μ²˜λ¦¬ν•œ 것 mark[c] 으둜 ν‘œμ‹œν•œλ‹€.
  • 단, 이미 κ²°κ³Ό result 에 λ“€μ–΄κ°€ μžˆλŠ” λ¬Έμžλ“€ 쀑 ν˜„μž¬ 문자 s[i] 보닀 큰 λ¬ΈμžλŠ” κ²°κ³Όμ—μ„œ λ‹€μ‹œ λΉΌλ‚Έλ‹€.
    • κ·Έλž˜μ•Όλ§Œ 사전식 μˆœμ„œ (lexicographic order)에 따라 κ°€μž₯ μž‘μ€ λ¬Έμžμ—΄μ„ λ§Œλ“€ 수 있기 λ•Œλ¬Έμ΄λ‹€.
    • 단, λΉΌλ‚Ό λ¬Έμžμ—΄μ΄ λ§ˆμ§€λ§‰ lastIndex[s[i] - 'a'] 에 해당될 경우 빼지 μ•Šκ³  κ·ΈλŒ€λ‘œ λ‘”λ‹€.
    • λΉΌλ‚Έ λ¬Έμžμ—΄μ€ μ²˜λ¦¬κ°€ μ•ˆλœ 것이기 λ•Œλ¬Έμ— ν‘œμ‹œλ₯Ό λ‹€μ‹œ 원상 볡ꡬ μ‹œν‚¨λ‹€ mark[s[i]] = false .
  • ν•΄λ‹΅μ—μ„œλŠ” stack을 μ‚¬μš©ν•˜λŠ” κ²ƒμœΌλ‘œ λ˜μ–΄μžˆλŠ”λ° κ°œλ…μ μœΌλ‘œλŠ” κΌ­ stack이라고 생각할 ν•„μš”λŠ” μ—†λ‹€.
    • λ³Έμ§ˆμ μœΌλ‘œλŠ” κ²°κ³Ό result μ—μ„œ ν˜„μž¬ 문자 보닀 큰 것 (단, λ§ˆμ§€λ§‰μΈ 것은 μ œμ™Έ)은 λͺ¨λ‘ μ œκ±°ν•˜κ³  ν˜„μž¬ 문자λ₯Ό 끝에 μΆ”κ°€ (append) ν•˜λŠ” 것일 뿐이닀.
    • λ‹€λ§Œ κ²°κ³Ό result μ—μ„œ 문자λ₯Ό λ’€μ—μ„œ λΆ€ν„° μ œκ±°ν•˜λŠ” 것이 νš¨μœ¨μ μ΄λΌμ„œ stack 처럼 popν•˜λŠ” λ°©μ‹μœΌλ‘œ μ œκ±°ν•  뿐이닀.
class Solution { public: static constexpr int CHARS = 'z' - 'a' + 1; string removeDuplicateLetters(string s) { // get last index of each characters vector<int> lastIndex(CHARS); for (int i = 0; i < s.length(); ++i) { lastIndex[s[i] - 'a'] = i; } vector<char> result; vector<bool> mark(CHARS); for (int i = 0; i < s.length(); ++i) { // skip character if marked if (mark[s[i] - 'a']) continue; while (!result.empty()) { char top = result.back(); // remove bigger characters from stack // except if the character is last one. if (top > s[i] && i < lastIndex[top - 'a']) { mark[top - 'a'] = false; result.pop_back(); } else { break; } } // add current character & mark result.push_back(s[i]); mark[s[i] - 'a'] = true; } // convert into string return string(result.begin(), result.end()); } };