๐๊ณต๋ถํ ๊ฑฐ List๐
- ์ข ๋ง๋ถ - 26. ํธ๋ผ์ด
- ์ข ๋ง๋ถ - (์ถ๊ฐ) ๊ทธ๋ํ๋ก ํ ์ ์๋ ๋ฌธ์ ์ ํ
- ์ข ๋ง๋ถ - 28. ๊ทธ๋ํ์ ๊น์ด ์ฐ์ ํ์
-
๋ฌธ์์ด์ ์งํฉ์ ํํํ๋ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ๋ก, ์งํฉ ๋ด์์ ์ํ๋ ์์๋ฅผ ์ฐพ๋ ์์ ์ O(M) (M์ ๋ฌธ์์ด์ ์ต๋ ๊ธธ์ด) ๋ง์ ํ ์ ์๊ฒ ํ๋ค.
-
์งํฉ์ ํฌํจ๋ ๋ฌธ์์ด์ ์ ๋์ฌ๋ค์ ๋์๋๋ ๋ ธ๋๋ค์ด ์๋ก ์ฐ๊ฒฐ๋ ํธ๋ฆฌ์ด๋ค.
- ํธ๋ผ์ด์ root๋ ํญ์ ๊ธธ์ด 0์ธ ๋ฌธ์์ด์ ๋์๋๊ณ , ๋ ธ๋์ ๊น์ด๊ฐ ๊น์ด์ง ๋๋ง๋ค ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ 1์ฉ ๋์ด๋๋ค.
- ์ข ๋ฃ๋ ธ๋ : ํด๋น ์์น์ ๋์๋๋ ๋ฌธ์์ด์ด ํธ๋ผ์ด๊ฐ ํํํ๋ ์งํฉ์ ํฌํจ๋์ด ์๋ค๋ ์๋ฏธ
- ๋ฃจํธ์์ ํ ๋ ธ๋๊น์ง ๋ด๋ ค๊ฐ๋ ๊ฒฝ๋ก์์ ๋ง๋๋ ๊ธ์๋ค์ ๋ชจ์ผ๋ฉด ํด๋น ๋ ธ๋์ ๋์๋๋ ๋ฌธ์์ด์ ์ป์ ์ ์๋ค.
- ํธ๋ผ์ด์ ๋ ธ๋ ๊ฐ์ฒด = ์์ ๋ ธ๋๋ค์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ ๋ชฉ๋ก + ์ข ๋ฃ๋ ธ๋์ธ์ง ๋ํ๋ด๋ boolean๊ฐ ๋ณ์
TrieNode
: ํธ๋ผ์ด์ ๋
ธ๋ ํ๋๋ฅผ ํํํ๋ ๊ฐ์ฒด
ALPHABET
: ๋ฌธ์์ด์ ์ถํํ ์ ์๋ ๋ฌธ์์ ๊ฐ์
toNumber()
: ์ฃผ์ด์ง ๋ฌธ์๋ฅผ ์ซ์๋ก ๋ณํ (0~ALPHABET-1)
insert()
: ํธ๋ผ์ด์ ์ ๋ฌธ์์ด์ ์ถ๊ฐํ๋ ํจ์
find()
: ํธ๋ผ์ด์ ํน์ ๋ฌธ์์ด์ด ์กด์ฌํ๋์ง ํ์ธํ๋ ํจ์
//ํ์ํ ํค๋
#include <cstring> //memset
๐ฉ์ฃผ์ ๋ฏธ์์ฑ๋ถ๋ถ์์
const int ALPHABETS = 26; //์ ์ฒด ์ํ๋ฒณ ๋๋ฌธ์ ๊ฐ์๋ 26๊ฐ
int toNumber(char ch) {
return ch - 'A';
}
struct TrieNode {
TrieNode* children[ALPHABETS]; //์์๋
ธ๋๋ค์ ํฌ์ธํฐ ๋ชฉ๋ก(๋์ ๋ฐฐ์ด์ด ์๋ ๊ณ ์ ๋ฐฐ์ด ์ฌ์ฉ)
bool terminal; //์ข
๋ฃ๋
ธ๋์ธ๊ฐ?
TrieNode() : terminal(false) {//์์ฑ์(๋ชจ๋ ํธ๋ผ์ด ๋
ธ๋์ ์ข
๋ฃ๋
ธ๋์ฌ๋ถ๋ฅผ false๋ก ์ค์ )
memset(children, 0, sizeof(children)); //์์๋ค์ ํฌ์ธํฐ ๋ชฉ๋ก์ 0์ผ๋ก ์ด๊ธฐํ
}
~TrieNode() { //์๋ฉธ์
for(int i=0; i<ALPHABETS; ++i) {
if(children[i]) delete children[i];
}
}
//์ด ๋
ธ๋๋ฅผ ๋ฃจํธ๋ก ํ๋ ํธ๋ฆฌ์ ๋ฌธ์์ด key๋ฅผ ์ถ๊ฐ
void insert(const char* key) {
if(*key == 0) terminal = true; //๋ฌธ์์ด์ด ๋๋๋ฉด ์ข
๋ฃ๋
ธ๋์ฌ๋ถ๋ฅผ ์ฐธ์ผ๋ก ๋ฐ๊พผ๋ค
else {
int next = toNumber(*key);//๋ฌธ์์ด์ ์ซ์๋ก ๋ณํ ํ next์ ์ ์ฅ
if(children[next] == NULL) //next์ ์์๋
ธ๋๊ฐ ์๋ค๋ฉด
children[next] = new TrieNode(); //์์๋
ธ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ค๋ค
children[next]->insert(key+1);//์์๋
ธ๋๊ฐ์ฒด๋ก ์ฌ๊ทํธ์ถ
}
}
//์ด ๋
ธ๋๋ฅผ ๋ฃจํธ๋ก ํ๋ ํธ๋ผ์ด์ ๋ฌธ์์ด key์ ๋์๋๋ ๋
ธ๋๋ฅผ ์ฐพ๊ณ ์์ผ๋ฉด NULL๋ฐํ
TrieNode* find(const char* key) {
if(*key == 0) return this; //๋ฌธ์์ด์ด ๋๋ฌ๋ค๋ฉด this๋ฅผ ๋ฐํํ๋ค(?)
int next = toNumber(*key); //๋ฌธ์์ด์ ์ซ์๋ก ๋ณํ ํ next์ ์ ์ฅ
if(children[next]==NULL) //์์๋
ธ๋๊ฐ ์๋ค๋ฉด
return NULL; //๋์๋๋ ๋
ธ๋๊ฐ ์๋ ๊ฒ์ด๋ฏ๋ก NULL๋ฐํ
return children[next]->find(key+1);//์์๋
ธ๋ ์ฌ๊ทํธ์ถ
}
}
- ์ฒ ๋๋ง์์ ํ ์ญ์ด ํ์๋ ๊ฒฝ์ฐ, ์ฒ ๋๋ง ์ ์ฒด๊ฐ ๋ ๊ฐ์ด์์ผ๋ก ์ชผ๊ฐ์ง ๊ฐ๋ฅ์ฑ์ด ์๋์ง ์์๋ด๋ ๋ฌธ์
- ์ญ์ ์ ์ ์ผ๋ก, ์ฒ ๋ก๋ฅผ ๊ฐ์ ์ผ๋ก ํํํ๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๊ณ ์ ๋จ์ ์ฐพ๊ธฐ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ํด๊ฒฐ
- ์น๋ถ๊ด๊ณ๋ฅผ ํํํ๋ ๋ฌธ์ (๋ช ๋ค๋ฆฌ ๊ฑด๋์ผ ์๋ ์ฌ์ด์ธ์ง, ํ ๋ค๋ฆฌ๊ฑด๋ ์๋ ์ฌ๋์ ๋ช ๋ช
์ธ์ง)
- ์ฌ๋์ ์ ์ ์ผ๋ก, ๊ด๊ณ๋ฅผ ๊ฐ์ ์ผ๋ก ํํํ๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๊ณ ๊ทธ๋ํ์ ๋๋น ์ฐ์ ํ์์ผ๋ก ํด๊ฒฐ
- ๋ ์ปดํจํฐ ๊ฐ ์ ์ก ์ฉ๋ ๊ณ์ฐํ๋ ๋ฌธ์ (์ ์ก์ฉ๋์ ์ฐ๊ฒฐ๋ ๊ฒ๋ค ์ค ์ต์ ์ ์ก์ฉ๋์ ๊ฐ๋ ์ผ์ด๋ธ์ ์ข์ฐ๋๋ค๊ณ ๊ฐ์ )
- ์ปดํจํฐ์ ๋ผ์ฐํฐ๋ฅผ ์ ์ ์ผ๋ก, ์ผ์ด๋ธ์ ๊ฐ์ ์ผ๋ก ํํํ๋ ๊ทธ๋ํ ์์ฑ ํ, MST์ด์ฉํ์ฌ ํด๊ฒฐ
- ํ ๋ถ ๊ทธ๋ฆฌ๊ธฐ ๋ฌธ์
- ๊น์ด ์ฐ์ ํ์์ ์์ฉํ ์ค์ผ๋ฌ ๊ฒฝ๋ก๋ฅผ ํตํด ํด๊ฒฐ
- ๊ฐ์ค์น์ ํฉ์ด ์์์ธ ์ฌ์ดํด ์ฐพ๊ธฐ ๋ฌธ์
- ์ต์ํ์ผ๋ก ํ์ผ์ ์์ง์ฌ 15-ํผ์ฆ์ ํธ๋ ๋ฌธ์
- ์ด๋ค ์์๋๋ก ์์
์ ์ฒ๋ฆฌํด์ผ ํ๋์ง ๊ณ์ฐํ๋ ๋ฌธ์
- ๊น์ด ์ฐ์ ํ์์ ์์ฉํ ์์์ ๋ ฌ ํด๊ฒฐ๋ฐฉ๋ฒ ์ด์ฉ
- ์ผ๋ถ ์นธ์ด ๋งํ์๋ ๋ธ๋ก๋ฌธ์ ์์ ๋งํ์์ง ์์ ๋ชจ๋ ์นธ์ ๋ธ๋ก์ ๋๋ ๋ฌธ์
- ์ํ์ข์ฐ๋ก ์ธ์ ํ ์นธ๋ค์ ๊ฐ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๊ณ ์ด๋ถ ๋งค์นญ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํด๊ฒฐ
- ๋ง์กฑ์ฑ ๋ฌธ์ : ํ์์ค ๋ฐฐ์ ๋ฌธ์
- ๋ ์ ์ ์ด ์๋ก ์ฐ๊ฒฐ๋์ด ์๋์ง ํ์ธํ๋ ๋ฌธ์
- ์ฐ๊ฒฐ๋ ๋ถ๋ถ์งํฉ์ ์ ์ธ๋ ๋ฌธ์
- ์์์ ๋ ฌ
- ์ค์ผ๋ฌ ๊ฒฝ๋ก
๊ทธ๋ํ์ ๋ชจ๋ ๊ฐ์ ์ ์ ํํ ํ ๋ฒ์ฉ ์ง๋์ง๋ง, ์์์ ๊ณผ ๋์ ์ด ๋ค๋ฅธ ๊ฒฝ๋ก
์ค์ผ๋ฌ ํธ๋ ์ผ์ ์กด์ฌ ์กฐ๊ฑด : ์์์ ๊ณผ ๋์ ์ ์ ์ธํ ๋ชจ๋ ์ ์ ์ง์์ ์ด๊ณ ์์์ ๊ณผ ๋์ ์ ํ์์ ์ด์ด์ผ ํ๋ค.
๊ทธ๋ํ์ ๋ชจ๋ ์ ์ ์ ์ ํํ ํ ๋ฒ์ฉ ์ง๋๋ ๊ฒฝ๋ก
๋ชจ๋ ์ ์ ์ ๋ฐฐ์ด์ ํ๋ํ๋ ์๋ํ๋ฉฐ ์ด๋ค์ด ๊ฒฝ๋ก๊ฐ ๋๋์ง ํ์ธํ๋, ์กฐํฉํ์์ผ๋ก ์ฐพ์ ์ ์๋ค. (๐คฆโโ๏ธ๋ฌธ์ ์ : ๊ฒฝ์ฐ์ ๋ฐ๋ผ ๋๋ฌด ๋ง์ ํ๋ณด๊ฐ ์์ ์ ์์)
๋จ์ด๋ค์ ๋ชฉ๋ก์ด ์ฃผ์ด์ง ๋, ๋จ์ด๋ค์ ์ ๋ถ ์ฌ์ฉํ๊ณ ๊ฒ์์ด ๋๋ ์ ์๋์ง, ๊ทธ๋ด ์ ์๋ค๋ฉด ์ด๋ค ์์๋ก ๋จ์ด๋ฅผ ์ฌ์ฉํด์ผ ํ๋์ง๋ฅผ ๊ณ์ฐํ๋ ๋ฌธ์
โก๏ธkeypointโก๏ธ
- ์ ๋ ฅ์ ์ฃผ์ด์ง ๊ฐ ๋จ์ด๋ฅผ ๊ฐ์ ์ผ๋ก ๊ฐ๋ ๋ฐฉํฅ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๊ณ , ์ ์ ์ ๊ฐ์ ์ ์ฒซ ๊ธ์์ ๋ง์ง๋ง ๊ธ์๋ก ํ๋ค.
adj
: ๊ทธ๋ํ์ ์ธ์ ํ๋ ฌ
indegree
, outdegree
: ๊ฐ๊ฐ ์ ์ ์ผ๋ก ๋ค์ด์ค๋ ๊ฐ์ ์ ์, ๋๊ฐ๋ ๊ฐ์ ์ ์
graph
: ๋ ์ ์ ์ฌ์ด๋ฅผ ์๋ ๊ฐ์ ๋ค์ด ๋ํ๋ด๋ ๋จ์ด์ ๋ชฉ๋ก
vector<vector<int>> adj;
vector<string> graph[26][26];
vector<int> indegree, outdegree;
void makeGraph(const vector<string>& words) {
for(int i=0; i<26; ++i) {
for(int j=0; j<26; ++j)
graph[i][j].clear();
}
adj = vector<vector<int>>(26, vector<int>(26,0));
indegree = outdegree = vector<int>(26,0);
for(int i=0; i<words.size(); ++i) {
int a = words[i][0] - 'a';
int b = words[i][words[i].size()-1] - 'a';
graph[a][b].push_back(words[i]);
adj[a][b]++;
outdegree[a]++;
indegree[b]++;
}
}
๋ฐฉํฅ ๊ทธ๋ํ์์ ์ค์ผ๋ฌ ์ํท์ ์กด์ฌ ์กฐ๊ฑด
- ๊ฐ ์ ์ ์ ๋ค์ด์ค๋ ๊ฐ์ ์ ์์ ๋๊ฐ๋ ๊ฐ์ ์ ์๊ฐ ๊ฐ์์ผ ํ๋ค.
๋ฐฉํฅ ๊ทธ๋ํ์์ ์ค์ผ๋ฌ ํธ๋ ์ผ์ ์กด์ฌ ์กฐ๊ฑด
- ์์์ ์ด a, ๋์ ์ด b์ผ ๋,
a์์ ๋๊ฐ๋ ๊ฐ์ ์ ์ = ๋ค์ด์ค๋ ๊ฐ์ ์ ์ + 1
์ด ๋์ด์ผํ๊ณ , b์์๋๋ค์ด์ค๋ ๊ฐ์ ์ ์ = ๋๊ฐ๋ ๊ฐ์ ์ ์ + 1
์ด์ด์ผ ํ๋ค.
๊ฐ ์ ์ ์ ์ฐจ์๋ฅผ ํ์ธํ์!
getEulerCircuit
: ์ค์ผ๋ฌ ์ํท ํน์ ํธ๋ ์ผ์ ๊ฒฝ๋ก๋ฅผ ๊ณ์ฐ
void getEulerCircuit(int here, vector<int>& circuit) {
for(int there=0; there<adj.size(); ++there) { //๋ชจ๋ ์ ์ ์ ๋ํด
while(adj[here][there] > 0) {//์ฐ๊ฒฐ๋ ์ ์ ์ด ์๋ ํ
adj[here][there]--; //<here-there> ๊ฐ์ ์ ๊ฐํ๊ณ
getEulerCircuit(there, circuit); //์ฐ๊ฒฐ๋ ์ ์ ์ ๋ํด ํจ์์ฌ๊ทํธ์ถ
}
}
circuit.push_back(here); //๊ฒฝ๋ก์ ์ถ๊ฐ
}
getEulerTrailOrCircuit
: ํ์ฌ ๊ทธ๋ํ์ ์ค์ผ๋ฌ ํธ๋ ์ผ์ด๋ ์ํท์ ๋ฐํ
vector<int> getEulerTrailOrCircuit() {
vector<int> circuit;
for(int i=0; i<26; ++i) { //๋ชจ๋ ๋ฌธ์์ ์ ์ ๋ํด
if(outdegree[i] == indegree[i] + 1) {//๋๊ฐ๋ ๊ฐ์ ์ด ๋ค์ด์ค๋ ๊ฐ์ ๋ณด๋ค ํ ๊ฐ ๋ ๋ง์ ๊ฒฝ์ฐ๋ผ๋ฉด, ์ค์ผ๋ฌ ํธ๋ ์ผ
getEulerCircuit(i, circuut); //๊ฒฝ๋ก๋ฅผ ๊ณ์ฐํ๋ค
return circuit; //๊ณ์ฐ๋ ๊ฒฝ๋ก๋ฅผ ๋ฐํ
}
}
for(int i=0; i<26; ++i) { //๋ชจ๋ ๋ฌธ์ ์ ์ ์ ๋ํด
if(outdegree[i]) { //์ค์ผ๋ฌ ํธ๋ ์ผ์ด ์๋๋ฉด ์ค์ผ๋ฌ ์ํท
getEulerCircuit(i, circuit); //๊ฒฝ๋ก๋ฅผ ๊ณ์ฐํ๋ค
return circuit; //๊ณ์ฐ๋ ๊ฒฝ๋ก๋ฅผ ๋ฐํ
}
}
return circuit; //๊ฒฝ๋ก ๊ณ์ฐ์ ์คํจํ์ผ๋ฉด ๋น ๋ฐฐ์ด ๋ฐํ
}
์กด์ฌ ์กฐ๊ฑด ํ์ธํ๊ธฐ!
(= ์ค์ผ๋ฌ ํธ๋ ์ผ์ด ์กด์ฌํ๋์ง ํ์ธํ๊ณ , ์กด์ฌํ๋ ๊ฒฝ์ฐ ์ถ๋ ฅ ๋ฌธ์์ด์ ๊ณ์ฐํด ๋ฐํํ๋ ์๊ณ ๋ฆฌ์ฆ)
checkEuler()
: ํ์ฌ ๊ทธ๋ํ์ ์ค์ผ๋ฌ ์ํท/ํธ๋ ์ผ ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ํจ์
solve()
: ๊ฒฝ๋ก๋ฅผ ๋ฌธ์์ด๋ก ๋ฐํํ์ฌ ์ถ๋ ฅํ๋ ํจ์
๐ข **<์ฐธ๊ณ > ์ผ๋ถ ๋ณ์๋ช ์ ๋ฐ๊พธ์์ผ๋, ์ฝ๋๋ด์ฉ์ ์ฑ ๊ณผ ๋์ผํฉ๋๋ค. **
bool checkEuler() {
int startCnt = 0; //์๋น์์์ ๊ฐ์ ์นด์ดํธ
int endPoint = 0; //์๋น๋์ ๊ฐ์ ์นด์ดํธ
for(int i=0; i<26; ++i) {
int diff = outdegree[i] - indegree[i];//์
์ถ๊ฐ์ ๊ฐ์์ฐจ์ด
if(diff < -1 ||diff > 1) return false; //์ฐจ์ด๊ฐ +1์ด๊ณผ, -1๋ฏธ๋ง์ด๋ฉด ์ค์ผ๋ฌ ์ํท/ํธ๋ ์ผ ์๋จ
if(diff == 1) startCnt++; //๋๊ฐ๋ ๊ฐ์ ์ด ๋ ๋ง์ผ๋ฉด ์๋น์์์ ๊ฐ์ +1
if(diff == -1) endCnt++; //๋ค์ด์ค๋ ๊ฐ์ ์ด ๋ ๋ง์ผ๋ฉด ์๋น๋์ ๊ฐ์ +1
}
//์ด ๊ณ์ฐ๋ ์๋น์์์ , ์๋น๋์ ๊ฐ์๊ฐ 1์ผ ๋(=์ค์ผ๋ฌ ํธ๋ ์ผ) ํน์
//๋ ๋ค 0์ผ ๋(=์ค์ผ๋ฌ ์ํท)๋ง true๋ฐํ
return (startCnt==1 && endCnt==1) || (startCnt==0 && endCnt==0)
}
string solve(const vector<string>& words) {
makeGraph(words); //๊ทธ๋ํ ๋ง๋ค๊ณ
if(!checkEuler()) return "IMPOSSIBLE"; //์ค์ผ๋ฌ ์ํท/ํธ๋ ์ผ ์๋๋ฉด impossible๋ฐํ
//์๋๋ผ๋ฉด ์ค์ผ๋ฌ ์ํท์ด๋ ํธ๋ ์ผ์ด๋ผ๋ ๊ฒ์ด๋ฏ๋ก
vector<int> circuit = getEulerTrailOrCircuit(); //๊ณ์ฐ๋ ๊ฒฝ๋ก๋ฅผ circuit์ ์ ์ฅ
if(circuit.size() != words.size()+1) return "IMPOSSIBLE"; //๋ชจ๋ ๊ฐ์ ์ ๋ฐฉ๋ฌธํ๋์ง ํ์ธ
//์ฌ๊ธฐ๊น์ง์๋ค๋ฉด, ์ ์์ ์ธ ์ค์ผ๋ฌ ์ํท/ํธ๋ ์ผ ๊ฒฝ๋ก๋ผ๋ ๊ฒ์ด๋ฏ๋ก
reverse(circuit.begin(), circuit.end()); //๊ฒฝ๋ก ์์๋ฅผ ๋ฐ๊ฟ์ฃผ์ด ์์์ ๋ถํฐ ๋์ ์์๋ก ๋ฐฐ์ดํด์ฃผ๊ณ
string ret; //๋ต์ผ๋ก ์ถ๋ ฅํ๊ฒ ๋ ๋ฌธ์์ด ๋ณ์ ์์ฑ
for(int i=0; i<circuit.size(); i++) {//๊ฒฝ๋ก์ ์ ์ ์๋งํผ
int a = circuit[i-1]; //์์์
int b = circuit[i]; //๋์
if(ret.size()) ret += " "; //์ ์ ์ฌ์ด์ ๊ณต๋ฐฑ๋ฌธ์์ด ์ถ๊ฐํด์ฃผ๊ณ
ret += graph[a][b].pop_back(); //๋ฌธ์์ด์ ์ ์ ์ ์ฅ
}
return ret; //๊ฒฐ๊ณผ ๋ฐํ
}
โฑTime Complexityโฑ
O(nA) : n์ ๋จ์ด์ ์, A๋ ์ํ๋ฒณ์ ์