코딩테스트 연습
프로그래머스 - 표현 가능한 이진트리
gurwhddl
2023. 8. 21. 16:29
문제
[https://school.programmers.co.kr/learn/courses/30/lessons/150367#]
내가 이해한 방법은, 이진트리 -> 숫자 표현 가능한지를 구하는 것보다 숫자 -> 이진트리로 나타냈을 때 해당 이진트리가 존재할 수 있는지?를 구해봄
노드 순서
제일 어려웠던 점이 노드의 순서였는데,
- 이진트리에서 리프 노드가 아닌 노드는 자신의 왼쪽 자식이 루트인 서브트리의 노드들보다 오른쪽에 있으며, 자신의 오른쪽 자식이 루트인 서브트리의 노드들보다 왼쪽에 있다고 가정합니다.
부모 / 왼쪽 자식 / 오른쪽 자식이 있다고 가정했을 때
어느 관점에서 보아도 부모는 항상 왼쪽 자식보다는 늦게 오고, 오른쪽 자식보다는 먼저 온다는 말을 저렇게 표현한듯...
이 말인 즉슨 제일 최상단의 루트 노드의 순서는 전체 노드의 개수/2가 된다는 뜻이고, 각 서브트리의 루트 노드의 순서는 항상 짝수가 됨
포화 이진트리 만들기
십진수 -> 이진수로 변환했을 때 그 길이가 노드의 개수가 됨
포화 이진트리가 되기 위해서는 노드의 개수가 항상 1,3,7,...2^n-1개를 유지해야 되기 때문에
- 앞에 0을 삽입해서 길이를 2^n-1로 맞춰줘야 함
- 당연히 0을 중간에 삽입할 수는 없음(그러면 다른 수가 되어버리기 때문에)
이제 중요한 건 어떤 조건에서 이진트리가 되지 못하는가?인데
처음에 생각한 건 각 서브트리의 루트 노드가 0일 때였는데,
128 - '10000000'
- 8자리이기 때문에 2^n-1을 맞추기 위해서 '000000010000000'로 바꿔줘야 하고, 이렇게 되면 최상단 루트 노드만 1이고 나머지는 모두
더미 노드가 됨 - 이 경우도 전혀 문제 없음 - 꼭 최하단 노드에서만 더미 노드를 추가할 수 있는 게 아님
본인의 부모 노드가 0,즉 더미 노드일 때 자식이 1 - 이 경우는 불가능(애초에 더미 노드를 추가하는 이유는, 128과 같이 포화 이진트리를 만들기 위해서이기 때문)
- 부모가 1일 때 더미 0 추가 or 부모가 0일 때(더미일때) 더미 0 추가 이 두 가지 경우밖에 될 수가 없음
그래서 top-down 방식으로 본인의 자식 노드를 조사하면서, 본인이 0인데 자식이 1인 경우는 표현할 수 없는 이진트리 가 됨
코드
function solution(numbers) {
const s = []
for(const number of numbers){
let string = number.toString(2)
let i = string.length
let sum = 0
while(i>=1){
sum++
i /= 2
}
let result = 0
string = string.padStart(2**sum-1,'0')
const a = findChildren([Math.floor(string.length/2)+1],sum-1,string)
if(a === true){
s.push(1)
}else{
s.push(0)
}
}
//자릿수에서 가장 가까운 수를 알아야함
function findChildren(arr, sum, string) {
if (!arr.length) {
return false;
}
if (sum <= 0) {
return true
}
const result = [];
for (let root of arr) {
const [left, right] = [root - (2**(sum-1)), root + (2**(sum-1))];
if (string[root - 1] == 0 && string[left - 1] == 1) {
return false;
}
if (string[root - 1] == 0 && string[right - 1] == 1) {
return false;
}
result.push(left);
result.push(right);
}
return findChildren([...result], sum - 1, string); // Note the "return" here
}
return s
}