문제
- 문제 링크
- 문제 설명: 카카오 프렌즈를 두 팀으로 나누고, 각 팀이 같은 곳을 다른 순서로 방문하도록 해서 먼저 순회를 마친 팀이 승리하는 것. 라이언은 방문할 곳의 2차원 좌표 값을 구하고 각 장소를 이진트리의 노드가 되도록 구성한 후, 순회 방법을 힌트로 주어 각 팀이 스스로 경로를 찾도록 할 계획. 라이언은 아래와 같은 특별한 규칙으로 트리 노드들을 구성한다.
- 트리를 구성하는 모든 노드의 x, y 좌표 값은 정수이다.
- 모든 노드는 서로 다른 x값을 가진다.
- 같은 레벨(level)에 있는 노드는 같은 y 좌표를 가진다.
- 자식 노드의 y 값은 항상 부모 노드보다 작다.
- 임의의 노드 V의 왼쪽 서브 트리(left subtree)에 있는 모든 노드의 x값은 V의 x값보다 작다.
- 임의의 노드 V의 오른쪽 서브 트리(right subtree)에 있는 모든 노드의 x값은 V의 x값보다 크다.
- 이진트리를 구성하는 노드들의 좌표가 담긴 배열 nodeinfo가 매개변수로 주어질 때, 노드들로 구성된 이진트리를 전위 순회, 후위 순회한 결과를 2차원 배열에 순서대로 담아 반환하는 함수를 작성
- 입력
- nodeinfo의 길이는 1 이상 10,000 이하
- nodeinfo[i] 는 i + 1번 노드의 좌표이며, [x축 좌표, y축 좌표] 순으로 들어있다.
- 모든 노드의 좌표 값은 0 이상 100,000 이하인 정수
- 트리의 깊이가 1,000 이하인 경우만 입력으로 주어진다.
- 출력: 전위 순회, 후위 순회 결과를 저장한 배열
풀이
- 이진 트리는 비단말 노드가 자식 노드를 최대 2개만 가질 수 있기 때문에 y좌표 내림차순, x좌표 오름차순으로 정렬한 후 값이 큰 y부터 차례대로 삽입하면 x값을 비교하면서 위의 조건들이 자연스레 만족되면서 위 그림과 같이 이진트리가 만들어짐
- 즉, 잘못된 순서로 입력되어지는 경우가 없기 때문에 다음 노드부터 x값 기준으로 부모보다 작으면 왼쪽 자식으로 크면 오른쪽 자식으로 보낸다. 둘 다 자식이 없으면 그 때는 자식을 생성한다.
- y값이 같은게 중간 레벨에 1개 있거나 3개 이상 있는 경우는 없으므로 제대로 동작
- 맨 처음에 좌표마다 노드 번호를 저장 map<pii, int>
- 주의할 점: 전위 순회, 후위 순회는 일반적으로 알고 있는 순회가 아닌 그림의 순서를 참고해야 함.
- 정답 코드
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#define X first
#define Y second
using namespace std;
typedef pair<int,int> pii;
map<pii, int> m;
struct Node {
pii c;
Node* l;
Node* r;
Node(pii c): c(c), l(nullptr), r(nullptr) {}
void insert(pii p) {
if (c.X > p.X) {
if (l) l->insert(p);
else l = new Node(p);
} else {
if (r) r->insert(p);
else r = new Node(p);
}
}
void preorder(vector<int>& v) {
v.push_back(m[c]);
if (l) l->preorder(v);
if (r) r->preorder(v);
}
void postorder(vector<int>& v) {
if (l) l->postorder(v);
if (r) r->postorder(v);
v.push_back(m[c]);
}
};
vector<vector<int>> solution(vector<vector<int>> nodeinfo) {
for (int i = 0; i < nodeinfo.size(); i++)
m[{nodeinfo[i][0], nodeinfo[i][1]}] = i+1;
sort(nodeinfo.begin(), nodeinfo.end(), [&](auto& a, auto& b) mutable {
if (a[1] == b[1]) return a[0] < b[0];
return a[1] > b[1];
});
// 이진 트리 생성
Node* root = new Node({nodeinfo[0][0], nodeinfo[0][1]});
for (int i = 1; i < nodeinfo.size(); i++)
root->insert({nodeinfo[i][0], nodeinfo[i][1]});
vector<int> v1, v2;
root->preorder(v1); // 전위 순회
root->postorder(v2); // 후위 순회
return {v1, v2};
}
'Algorithm > Problem Solving' 카테고리의 다른 글
[String, Trie] (프로그래머스 Lv 4) 가사 검색 (0) | 2021.04.24 |
---|---|
[String, 구현] (프로그래머스 Lv 3) 매칭 점수 (0) | 2021.04.24 |
[BFS] (프로그래머스 Lv 3) 블록 이동하기 (0) | 2021.04.24 |
[완전 탐색, DP] (프로그래머스 Lv 3) 외벽 점검 (0) | 2021.04.24 |
[DFS] (프로그래머스 Lv 3) 카드 짝 맞추기 (0) | 2021.04.24 |