본문 바로가기

CS/데일리 Problem Solving

2025-01월 Algoirthm

Baekjoon - 이진 트리(13325번)

 

이진트리의 성질을 고찰해 볼 수 있는 문제이다. 우선 문제에서 주어진 트리가 포화 이진 트리이기 때문에 특수한 조건들이 많이 성립한다.

 

1. 전체 노드의 개수

우선 트리의 높이가 주어질 때, 전체 트리의 노드 개수를 구할 수 있다. 이는 등비수열의 합과 관련 있는데 아래와 같은 예를 한번 보자.

root: 1개

1층: 2개

2층: 4개

3층: 8개

4층: 16개

5층: 32개

총 노드의 개수는 1+2+4+8+16+32이다. 이는 초항이 1이고 등비가 2인 수열의 6번째 까지 항의 합으로 1*2^6-1/(2-1) = 63이다. 일반화 하면 포화 이진 트리의 노드 개수는 트리의 높이를 k라고 할 때, 2^(k+1)-1이다.

 

2. 부모 노드와 자식 노드의 관계

포화 이진 트리이기 때문에 모든 부모 노드는 자식의 개수가 2개이다. 또한 부모 노드의 인덱스를 알면 자식 노드의 인덱스를 알 수 있고 자식 노드의 인덱스를 알면 부모 노드의 인덱스를 알 수 있다.

 

전체 코드

import sys

tree_height = int(sys.stdin.readline())
edge_weight = [0,0]+list(map(int, sys.stdin.readline().split()))
node_n = 2**(tree_height+1)-1

s = [1]

def dfs(s):
    t = s.pop()
    if t*2 > node_n:
        return edge_weight[t]

    n1 = t*2
    n2 = t*2+1
    l_s = dfs(s+[n1])
    r_s = dfs(s+[n2])

    acc_s = l_s
    if l_s > r_s:
        acc_s = l_s
        edge_weight[n2] += l_s-r_s
    elif l_s < r_s:
        acc_s = r_s
        edge_weight[n1] += r_s-l_s

    return acc_s + edge_weight[t]
dfs(s)
print(sum(edge_weight))

 

 


 

 

Baekjoon -나무탈출(15900번)

트리에서 리프 노드인지 판별하는게 중요한 문제

 


Baekjoon -보드게임?()

 


Baekjoon - 후위 표기법(1918번)

문제에서 초기에 설명한 방법으로 풀려다가 실패하고... 풀이를 참조하였다. 

연산의 우선순위는 아래와 같다. 

1. () 괄호 안에 둘러쌓인 연산 부터 수행한다.

2. *, / 연산을 +, - 보다 먼저 수행한다.

3. 왼쪽에 있는 연산을 오른쪽 연산 보다 먼저 수행한다.

 

처음 고안한 풀이 방법은 아래와 같다. 

1. *, / 연산에 대하여 () 괄호를 추가한다.

2. () 괄호로 둘러쌓인 연산에 대하여 먼저 수행한다.

3. 2번 연산의 결과와 남아 있는 문자 그리고 +, - 연산자에 대하여 연산을 수행한다.

 


Baekjoon - 빵집(3109번)

2차원 배열에서 행을 x로 할지 열을 x로 할지에 대한 것 - 결국 통일성이 중요함.

새로운 스택을 구성하고 재귀함수를 실행하기 전, visited를 업데이트 하는것의 의미 - 상관이 없는 이유

dictionary -> list로 변경함으로써 메모리를 절약하는 방법

 


Baekjoon - 저울(2437번) *** 

발상의 전환이 필요했던 문제.

그리디보다 DP의 개념과 더 유사했던 것 같은 문제

현재 W까지 만들 수 있었다면 1부터 W까지 만들 수 있는 것이고 다음 추의 무게 W`에 대하여 1부터 W까지 W`에 더한 값을 만들 수 있다는 개념이 중요했던 문제이다.

 

전체 코드

import sys

n = int(sys.stdin.readline())

w_l = sorted(list(map(int, sys.stdin.readline().split())))

### 1. 첫번째 접근 방법

# upper_limit = sum(w_l)

# dp = [0 for _ in range(upper_limit+1)]
# report = [0 for _ in range(upper_limit+1)]
# for i in range(n):
#     dp[0] = 1

# for w in w_l:
#     for j in range(upper_limit, w-1, -1):
#         dp[j] += dp[j-w]

# for i in range(upper_limit+1):
#     if dp[i] == 0:
#         print(i)
#         break



### 2. 풀이를 참고한 접근 방법

num_sum = 0
for w in w_l:
    if num_sum + 1 < w:
        print(num_sum +1)
        break
    num_sum += w
else:
    print(num_sum + 1)

Baekjoon - 트리의 높이와 너비(2250번) 

트리를 조회하는 순서가 중요했던 문제, 전위순회 후위순회 중위순회 등과 연계 될 수도...

변수를 사용하던 것을 그대로 사용하는것과 새로 만드는 것의 차이가 중요했던 문제

전체 코드

import sys

n_num = int(sys.stdin.readline())

root = n_num*(n_num+1)/2
tree = {}
for _ in range(n_num):
    temp = list(map(int, sys.stdin.readline().split()))
    p_n = temp[0]
    c_l = temp[1:]
    tree[p_n] = c_l
    if c_l[0] != -1:
        root -= c_l[0]
    if c_l[1] != -1:
        root -= c_l[1]

s = [root]
col = {}
depth_num = {}
def dfs(s, extra, depth):
    t = s.pop()
    l_n, r_n = tree[t]

    cur_num_l = 0
    if l_n != -1:
        cur_num_l = dfs(s+[l_n], extra, depth+1)
    col[t] = cur_num_l +1 + extra
    if depth not in depth_num:
        depth_num[depth] = [col[t]]
    else:
        depth_num[depth].append(col[t])

    cur_num_r = 0
    if r_n != -1:
        cur_num_r = dfs(s+[r_n], extra + cur_num_l+1, depth+1)
    return cur_num_l +1  + cur_num_r

dfs(s, 0, 1)

final = []
for d in depth_num:
    if len(depth_num[d]) >1:
        final.append([max(depth_num[d])-min(depth_num[d])+1,d])
if len(final) != 0:
    answer = sorted(final, key = lambda x : [-x[0], x[1]])[0]
    print(answer[1], answer[0])
else:
    print(1, 1)

'CS > 데일리 Problem Solving' 카테고리의 다른 글

2025-05 Algorithm  (1) 2025.05.08
2025-04 Algorithm  (0) 2025.04.03
2025-03 Algorithm  (0) 2025.03.05
2025-02월 Algoirthm  (0) 2025.02.06