티스토리 뷰
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/150367
해결 방법
- 10진수를 이진수로 바꾸기
- 포화 완전트리에 대한 개념을 이해
- 포화 이진트리가 만들어 지지 않는 경우를 이해하고 트리를 순회하는 방법에 대해 배워보자
10진수를 이진수로 바꾸기10진수를 2진수로 바꾸는 방법은 파이썬에서 여러가지 방법이 있지만 다른언어를 사용할 때를 대비하여 (자바스크립트) while문 만으로 구현하였다.
10진수를 이진수로 바꾸기
- n이 1이 될 때 까지 반복문을 반복한다.
- n을 계속 2로 나누고 나머지를 array에 저장한다.
- 반복문을 탈출 후 1을 append 해준 뒤 거꾸로 뒤집는다.
def convertBinary(n):
a = []
while 1 < n:
tmp = n % 2
a.append(tmp)
n = n // 2
a.append(1)
cnt = 0
idx = 1
while True:
if 2 ** idx - 1 >= len(a):
cnt = 2 ** idx - 1
break
idx += 1
a.reverse()
포화완전 트리에 대한 이해
포화 완전트리에 대한 이해포화 완전트리는 자식노드가 모두 존재하는 대칭을 이루는 트리를 말한다.
노드의 개수는 항상 2 ** level -1의 개수를 갖는다. 여기서 level은 트리의 층을 의미한다.
1층일 땐 1 개 2층일 땐 3개 3층일 땐 7개...
해당 문제의 경우 0은 더미노드로 표현을 하고 1은 실제 표현하는 노드가 된다.
다음은 42를 표현한 경우이다.
42를 포화완전트리 형태로 만들면 0101010으로 표현할 수 있게 되는데 더미노드를 모두 제거하고나면 다음과 같은 형태가 된다.
포화 완전트리를 만드는게 중요함으로 파이썬의 zfill을 사용해서 더미노드가 될 부분을 앞의 갯수만큼 0으로 채워준다. 파이썬이 아닌경우엔 for문으로 채워줄 것 같다
cnt = 0
idx = 1
while True:
if 2 ** idx - 1 >= len(a):
cnt = 2 ** idx - 1
break
idx += 1
a.reverse()
result = "".join(list(map(str,a)))
result = result.zfill(cnt)
이진트리 순회하기
이 부분이 이문제의 핵심이다.
자식노드가 존재하는데 부모노드가 되는 부분이 0인 경우엔 이진트리로 표현할 수 없기 때문에
- 부모노드를 탐색
- 자식 노드 중 1이 있는 경우에 따라 Ture, False 반환
하는 방법을 선택하였다.
def division_search(start, end, arr):
if start == end: # start와 end의 경우 리프노드를 의미함으로 탐색 종료
return True # 끝까지 탐색을 완료했음으로 True 반환
mid = (start + end) // 2
if arr[mid] == '0': # mid가 0인 경우
for i in range(start, mid): # left child 탐색
if arr[i] == '1': # 1 존재하면 False
return False
for i in range(mid + 1, end + 1): # right child 탐색
if arr[i] == '1': # 1 존재하면 False
return False
left = division_search(start, mid - 1, arr)
right = division_search(mid + 1, end, arr)
return left and right
전체 코드
def convertBinary(n):
a = []
while 1 < n:
tmp = n % 2
a.append(tmp)
n = n // 2
a.append(1)
cnt = 0
idx = 1
while True:
if 2 ** idx - 1 >= len(a):
cnt = 2 ** idx - 1
break
idx += 1
a.reverse()
result = "".join(list(map(str,a)))
result = result.zfill(cnt)
return result
def division_search(start, end, arr):
if start == end:
return True
mid = (start + end) // 2
if arr[mid] == '0':
for i in range(start, mid):
if arr[i] == '1':
return False
for i in range(mid + 1, end + 1):
if arr[i] == '1':
return False
left = division_search(start, mid - 1, arr)
right = division_search(mid + 1, end, arr)
return left and right
def solution(numbers):
answer = []
for n in numbers:
# flag = True
tmp = convertBinary(n)
arr = list(tmp)
flag = division_search(0, len(arr) - 1, arr)
if flag:
answer.append(1)
else:
answer.append(0)
return answer
'코딩테스트' 카테고리의 다른 글
[프로그래머스] 미로탈출 명령어 (0) | 2023.11.10 |
---|---|
[백준 1600] 말이되고픈 원숭이 (파이썬) (0) | 2023.09.13 |
[백준 22862] 가장 긴 짝수 연속한 부분 수열(Large) (0) | 2023.08.04 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 백준 1600번
- React useCallback
- nextjs 에러핸들링
- javascript
- 백준 22862
- 서버사이드 error handling
- 불량 사용자 자바스크립트
- suspense 장점
- 표현 가능한 이진트리
- 가장 긴 짝수 연속한 부분 수열
- storybook react is not defiend 해결
- react suspense
- 자바스크립트
- node version yarn berry
- serverless nestjs
- storybook scss import
- node 버전 마이그레이션
- serverless 배포
- React useMemo
- 서비스 디자인 패턴
- useCallback과 useMemo 사용
- 에러핸들링
- 미로탈출 명령어
- 1600 파이썬
- 관심사 분리하기
- CSS
- nestjs 배포하기
- storybook scss이슈
- nextjs errorboundary
- 선언적 UI
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함