1991_트리 순회 (Python)

0. 출처

1. 기록

  • 22/04/18 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 각 노드, 왼쪽 노드, 오른쪽 노드가 주어졌을 때
>> 어떻게 tree 에 저장할 것인지?
>> set() 형태로 저장해보자.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
7
A B C
B D .
C E F
E . .
F . G
D . .
G . .

- 예제 출력 1 -
ABDCEFG
DBAECFG
DBEGFCA

(3) 코드

n = int(input())

tree = {}

for _ in range(n):
    node, left, right = map(str, input().split())
    tree[node] = [left, right]

def preorder(root):              # 전위순회
    if root != '.':
        print(root, end='')      # root
        preorder(tree[root][0])  # left
        preorder(tree[root][1])  # right

def inorder(root):               # 중위순회
    if root != '.':
        inorder(tree[root][0])   # left
        print(root, end='')      # root
        inorder(tree[root][1])   # right

def postorder(root):             # 후위순회
    if root != '.':
        postorder(tree[root][0]) # left
        postorder(tree[root][1]) # right
        print(root, end='')      # root

preorder('A')
print()        # 줄바꿈 용도
inorder('A')
print()        # 줄바꿈 용도
postorder('A')

(4) 정리

재귀를 잘 이해해야 이해할 수 있는 풀이이다.

전위 순회, 중위 순회, 후위 순회 개념이 코드에 그대로 적용된 풀이이다.

(5) 참고

참고 풀이

[문제번호]_[문제이름] (Python)

0. 출처

1. 기록

  • 22/04/18 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 루트노드가 1인 정보가 주어져있다.
>> 그 외의 나머지는 연결관계만 주어져있다.
>> 이 경우 부모노드를 어떻게 파악하면 좋을까?
>> 우선 연결관계부터 만들어보자.

2. 시간복잡도
>>

3. 자료구조

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
7
1 6
6 3
3 5
4 1
2 4
4 7

- 예제 출력 1 -
4
6
1
3
1
4

- 예제 입력 2 -
12
1 2
1 3
2 4
3 5
3 6
4 7
4 8
5 9
5 10
6 11
6 12

- 예제 출력 2 -
1
1
2
3
3
4
4
5
5
6
6

(3) 코드

import sys

sys.setrecursionlimit(10**9)

n = int(input())

# 트리
tree = [[] for _ in range(n+1)]

# 부모 노드 저장
relation = [0 for _ in range(n+1)]

for _ in range(n-1):
    a, b = map(int, input().split())
    tree[a].append(b)
    tree[b].append(a)

def dfs(start, tree, relation):
    # 연결된 노드들부터 relation[i] 의 부모가 없으면 부모 설정해주고 dfs를 돌린다.
    for node in tree[start]:
        if relation[node] == 0:
            # node에게 너 여기서 출발했다고 표시해주는 느낌
            relation[node] = start
            dfs(node, tree, relation)

dfs(1, tree, relation)

for i in range(2, n+1):
    print(relation[i])

(4) 정리

(5) 참고

참고 풀이

1. 서류

지원서 작성을 해야합니다.
질문1. 본인이 최고라고 생각하거나 다른 사람보다 뛰어나다고 생각하는 항목과, 이를 성취하기 위한 노력과 과정에 대해 작성해 주십시오. (필수) * 800자

질문2. 해결하기 어려웠던 문제나 상황에서 남들이 하지 않은 새로운 시도/변화를 통해 기회를 창출하거나 문제를 해결한 경험에 대해 서술해 주십시오. (필수) * 800자

질문3. 지원 직무에 필요한 역량과 관련된 프로젝트/공모전/논문/연구/학습 및 기타 활동에 참여한 경험 1을 작성하여 주십시오. (필수) * 500자

질문4. 지원 직무에 필요한 역량과 관련된 프로젝트/공모전/논문/연구/학습 및 기타 활동에 참여한 경험 2을 작성하여 주십시오. (선택) * 500자

질문 1 ~ 3 필수항목 까지만 작성해서 제출하였습니다.

2. 안내 메일

보시다시피 외부 IDE는 사용가능하나 복사,붙여넣기가 안되어 직접 코드를 작성해야 합니다.(프로그래머스 내에서는 가능)

또한 검색이 가능하지만 권장하지 않는다고 명시되어 있으나 시험 내에서는 기억상 브라우저 등에 검색하면 안된다고 되어있었습니다.

시험 창 내부에 다음과 같이 documentation 링크가 있는데 documentation 내에서만 검색 가능하도록 시험을 치뤘습니다.

https://devdocs.programmers.co.kr/python~3.8/

[DevDocs — Python 3.8 documentation

devdocs.programmers.co.kr](https://devdocs.programmers.co.kr/python~3.8/)

3. 테스트 입장 전

4월 15일 (금)인 코딩테스트 전날에 데모테스트 사전체험을 하였습니다.

기본적으로 제공 동의 등 항목체크하고 노트북 화면 공유, 노트북 캠 연결, 신분증 촬영 후 제출, 핸드폰 카메라 연결 등의 사전작업을 미리 체험해보게 됩니다. (테스트 당일날도 다시 똑같이 진행해야 됨)

또한 듀얼모니터 사용이 안되어 노트북화면 1대로만 시험을 치뤘습니다. ★

그리고 촬영 중에 다른 외부인이 비춰지면 안되고 독립된 공간에서 치뤄야 한다는 조항도 있어서 집에서 치뤘습니다.

4. 본 테스트

3시간 동안 4문제를 풀도록 출제됩니다.

 

문제1 유형 : DFS 방식으로 풀었습니다.

 

문제2 유형 : 트리 + DP

root에서 시작해서 dfs 를 활용한다.

dfs(x)

: x를 root로 하는 rooted tree에서 x의 모든 자식들의 값 계산해주는 함수

이렇게 함수 정의를 잘해주면 dfs에서 바로 계산이 가능하다.

많이 나오는 예시이므로 암기할 것 ★

트리 + DP 의 가장 쉬운 버전이라고 생각하시면 됩니다. ★

함수의 역할 자체를 잘 정의해주면 이걸 호출하는 것 만으로도 자식들의 결과를 자신의 결과에 쓸 수 있기 때문에 작은 문제의 결과로 큰 문제의 값을 빠르게 계산할 수 있죠.

 

문제3 유형 : DP

 

문제4 유형 : 단순 구현

5. 소감

트리와 DP 유형의 문제를 평소 풀지 않았던 터라 생각하는 로직은 맞았으나 코드로 구현하기 어려웠습니다.

그래서 문제1과 문제4만 풀어서 제출했으며 문제2와 문제3은 풀지못하였습니다.

또한 IDE에서 프로그래머스로 옮기는 과정에서 오타가 생겨 테스트 케이스를 돌릴 때 에러가 계속 발생했는데 에러 발생 여부만 알려주고 어느 줄에 발생했는지도 안알려줘서 해결하는데 시간낭비를 좀 많이 하였습니다.(※ 주의)

어느정도 연습했던 분이라면 3솔까지는 무난하게 하시지 않았을까 하는 생각이 듭니다.

6. 코드

# Q1.
# C3
# => 52
import sys
si = sys.stdin.readline
n = int(si())
a = [[0 for _ in range(10)] for __ in range(10)]
for _ in range(n):
    coord = si().strip()  # 병사의 좌표, D7 => 4행 7열
    row = ord(coord[0]) - ord('A') + 1
    col = int(coord[1])
    dirs = [[-1, -1], [1, -1]]
    for dr, dc in dirs:
        for len in range(-7, 8):
            nr = row + dr * len
            nc = col + dc * len
            if 1 <= nr <= 8 and 1 <= nc <= 8:
                a[nr][nc] = 1

ans = 0
for i in range(1, 9):
    for j in range(1, 9):
        if a[i][j] == 0:
            ans += 1

print(ans)


# Q2.
# 6 121
# 1 2
# 1 3
# 3 4
# 3 6
# 3 5
import sys
si = sys.stdin.readline
n, k = map(int, si().split())
children = [[] for _ in range(n + 1)]
hasParent = [0 for _ in range(n + 1)]
for _ in range(n - 1):
    par, child = map(int, si().split())
    children[par].append(child)
    hasParent[child] = 1
value = [0 for _ in range(n + 1)]
def DFS(x):
    # x의 모든 자식들에 대해 value 계산해주기
    if not children[x]:  # x 밖에 없는 상황
        value[x] = 1
        return
    for child in children[x]:
        DFS(child)
        value[x] += value[child]
for i in range(1, n + 1):
    if not hasParent[i]:
        DFS(i)
total_value_sum = sum(value)
multiply = k // total_value_sum
for i in range(1, n + 1):
    print(value[i] * multiply, end=' ')


# Q3.
# 4 4
# 2 1 2 1 3 4 4 3
# 1 2 3 4
# => 4
import sys
INF = 1000000009
si = sys.stdin.readline
n, m = map(int, si().split())
a = list(map(int, si().split()))
smells = list(map(int, si().split()))
# 각 향기마다 A랑 B위치 기억해두기
place = [[-1, -1] for _ in range(n + 1)]
for i in range(n * 2):
    smell = a[i]
    if place[smell][0] == -1:
        place[smell][0] = i
    else:
        place[smell][1] = i


def get_dist(x, y):
    # x번 위치에서 y번 위치로 가는 최단거리 계산
    if x > y:
        x, y = y, x
    return min(y - x, n * 2 - (y - x))
# 배열 정의
dy = [[INF, INF] for _ in range(m + 1)]
dy[0][0], dy[0][1] = get_dist(0, place[smells[0]][0]), get_dist(0, place[smells[0]][1])
for i in range(1, m):
    prev = smells[i - 1]  # 직전에 맡은 향 번호
    cur = smells[i]       # 이번에 맡은 향 번호
    for cur_k in range(2):
        # dy[i][cur_k] 을 계산해줄 차례
        curPosition = place[cur][cur_k]
        prevA, prevB = place[prev][0], place[prev][1]
        dy[i][cur_k] = min(dy[i - 1][0] + get_dist(prevA, curPosition),  # 직전에 A번 위치 선택
                           dy[i - 1][1] + get_dist(prevB, curPosition))  # 직전에 B번 위치 선택
print(min(dy[m - 1]))


# Q4.
import sys
si = sys.stdin.readline
n = int(si())
a = [0] + list(map(int, si().split()))
b = [0 for _ in range(n + 1)]
for i in range(1, n + 1):
    for j in range(i, n + 1, i):
        b[j] += a[i]

for i in range(1, n + 1):
    print(b[i], end=' ')

모의고사 (Python)

0. 출처

1. 기록

  • 22/04/14 (목)

2. 풀이

(1) 아이디어

1. 아이디어
>> 1번 수포자 [1, 2, 3, 4, 5] 반복                    -> 5로 나눈 나머지
>> 2번 수포자 [2, 1, 2, 3, 2, 4, 2, 5] 반복           -> 8로 나눈 나머지
>> 3번 수포자 [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] 반복    -> 10으로 나눈 나머지

2. 시간복잡도
>>

3. 자료구조
>>

(2) 코드

def solution(answers):
    person1 = [1, 2, 3, 4, 5]
    person2 = [2, 1, 2, 3, 2, 4, 2, 5]
    person3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]

    answer_list = {'1':0, '2':0, '3':0}

    for i in range(len(answers)):
        if answers[i] == person1[i%5]:
            answer_list['1'] += 1
        if answers[i] == person2[i%8]:
            answer_list['2'] += 1
        if answers[i] == person3[i%10]:
            answer_list['3'] += 1

    max_value = max(answer_list.values())
    winner = []

    for key, value in answer_list.items():
        if max_value == value:
            winner.append(int(key))
    return winner

(3) 정리

일부러 dict 자료형을 써서 해결하려했고 unpacking 할 때 items() 함수를 써야하는 걸 정확히 알고 있지 않아서 에러가 계속생겼다.
하는 방법을 정확히 익혀두자!

(4) 참고

베스트앨범 (Python)

0. 출처

1. 기록

  • 22/04/14 (목)

2. 풀이

(1) 아이디어

sample

(2) 코드

sample

(3) 정리

(4) 참고

위장 (Python)

0. 출처

  • 유형 : 해시 (lv 2)
  • 링크 : 위장

1. 기록

  • 22/04/13 (수)

2. 풀이

(1) 아이디어

1. 아이디어
>>
2. 시간복잡도
>>
3. 자료구조
>>

(2) 코드

def solution(clothes):
    # 1. 옷을 종류별로 구분하기
    hash_map = {}
    for clothe, type in clothes:
        hash_map[type] = hash_map.get(type, 0) + 1

    # 2. 입지 않는 경우를 추가하여 모든 조합 계산하기
    answer = 1
    for type in hash_map:
        answer *= (hash_map[type] + 1)

    # 3. 아무종류의 옷도 입지 않는 경우 제외하기
    return answer - 1

(3) 정리

처음에 {type : [옷1, 옷2, 옷3]} 등으로 만들어야 하나 고민했으나
문제에서는 조건에 맞는 결과 값만 원하기 때문에 그럴 필요가 없음을 알게되었습니다.

위 코드처럼 list의 값 여러개를 여러변수에 동시에 할당하는 것을 unpacking이라 하는데 유용하게 쓸 수 있도록 연습해야할 것 같습니다.
또한 get() 함수 사용법 또한 익혀놔야겠습니다.

(4) 참고

참고 자료

[문제이름] (Python)

0. 출처

1. 기록

  • 22/04/13 (수)

2. 풀이

(1) 아이디어

1. 아이디어
>> 반복문 돌면서 기준이되는 폰넘버를 다른 폰넘버가 앞자리부터 가지고 있는지 확인해본다.
>> slicing 활용!

2. 시간복잡도
>>

3. 자료구조
>>

(2) 코드

# 효율성 테스트 3,4 실패

def solution(phone_book):
    phone_book.sort()
    for num in range(0, len(phone_book)):
        for target in range(num+1, len(phone_book)):
            target_num = phone_book[target]
            if phone_book[num] == target_num[0:len(phone_book[num])]:
                return False
    return True
# startswith() 를 활용하면 이중for문없이 해결할 수 있다.

def solution(phone_book):
    phone_book.sort()

    for num in range(0, len(phone_book)-1):
        if phone_book[num+1].startswith(phone_book[num]):
            return False
    return True
# startswith() 와 zip() 을 활용한 풀이

def solution(phoneBook):
    phoneBook.sort()

    print(phoneBook)
    print(phoneBook[1:])
    print(list(zip(phoneBook, phoneBook[1:])))

    for p1, p2 in zip(phoneBook, phoneBook[1:]):
        if p2.startswith(p1):
            return False
    return True

(3) 정리

(4) 참고

효율성 참고1
효율성 참고2
참고 풀이

완주하지 못한 선수 (Python)

0. 출처

1. 기록

  • 22/04/13 (수)

2. 풀이

(1) 아이디어

1. 아이디어
>> 정렬 후 비교해서
>> 다른 경우가 생기는 경우를 return 한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 코드

# 풀이1 : 리스트 정렬

def solution(participant, completion):
    p = sorted(participant)
    c = sorted(completion)

    for i in range(0, len(completion)):
        if p[i] != c[i]:
            return p[i]

    return p[-1]
# 풀이2 : hash 이용

def solution(participant, completion):
    hashDict = {}
    sumHash = 0
    # 1. Hash : Participant의 dictionary 만들기
    # 2. Participant의 sum(hash) 구하기
    for part in participant:
        hashDict[hash(part)] = part
        print(hashDict)
        sumHash += hash(part)

    # 3. completion의 sum(hash) 빼기
    for comp in completion:
        sumHash -= hash(comp)

    # 4. 남은 값이 완주하지 못한 선수의 hash 값이 된다
    return hashDict[sumHash]
# 풀이3 : counter 이용

import collections

def solution(participant, completion):
    # 1. participant의 Counter를 구한다
    # 2. completion의 Counter를 구한다
    # 3. 둘의 차를 구하면 정답만 남아있는 counter를 반환한다
    answer = collections.Counter(participant) - collections.Counter(completion)

    # 4. counter의 key값을 반환한다
    return list(answer.keys())[0]

(3) 정리

(4) 참고

참고 풀이
참고 영상

18430_[문제이름] (Python)

0. 출처

1. 기록

  • 22/04/11 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 특정 3칸을 차지하면 나머지 칸에서 ㄱ or ㄴ 형태로 3칸을 차지하는 모든 경우를 체크해서 
>> 문제에서 요구하는 사항에 맞는 최댓값을 갱신시킨다.
>> 특정 3칸을 이동하고 다시 반복
>> 특정 3칸 ㄱ or ㄴ 형태를 어떻게 입력시킬 것인지?
>> ┌, ┐, └, ┘ 각 4가지 모양을 기준으로 위의 로직을 반복한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
3 3
32 83 75
24 96 56
71 88 12

- 예제 출력 1 -
632

- 예제 입력 2 -
1 1
7

- 예제 출력 2 -
0

(3) 코드

# (0,0)부터 시작
# 시작점을 방문안했으면
#   부메랑 블럭이 범위 안에 있고, 방문안했으면 --> 강도 계산
# 시작점을 방문했으면
#   시작점 = 한칸 옆
def first(y, x):
    return woods[y][x-1] + 2*woods[y][x] + woods[y-1][x]


def second(y, x):
    return woods[y][x-1] + 2*woods[y][x] + woods[y+1][x]


def third(y, x):
    return woods[y+1][x] + 2*woods[y][x] + woods[y][x+1]


def fourth(y, x):
    return woods[y-1][x] + 2*woods[y][x] + woods[y][x+1]


def solve(y, x, strength):
    global N, M, answer
    if x == M:
        x = 0
        y += 1
    if y == N:
        answer = max(answer, strength)
        return
    if not visited[y][x]:
        if y - 1 >= 0 and x - 1 >= 0 and not visited[y][x-1] and not visited[y-1][x]:
            visited[y][x] = visited[y][x-1] = visited[y-1][x] = True
            this_strength = strength + first(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x-1] = visited[y-1][x] = False
        if y + 1 < N and x - 1 >= 0 and not visited[y+1][x] and not visited[y][x-1]:
            visited[y][x] = visited[y][x-1] = visited[y+1][x] = True
            this_strength = strength + second(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x-1] = visited[y+1][x] = False
        if y + 1 < N and x + 1 < M and not visited[y+1][x] and not visited[y][x+1]:
            visited[y][x] = visited[y][x+1] = visited[y+1][x] = True
            this_strength = strength + third(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x+1] = visited[y+1][x] = False
        if y - 1 >= 0 and x + 1 < M and not visited[y-1][x] and not visited[y][x+1]:
            visited[y][x] = visited[y][x+1] = visited[y-1][x] = True
            this_strength = strength + fourth(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x+1] = visited[y-1][x] = False
    solve(y, x+1, strength)


N, M = map(int, input().split())
woods = [list(map(int, input().split())) for _ in range(N)]
visited = [[False] * M for _ in range(N)]
answer = 0
solve(0, 0, 0)
print(answer)

(4) 정리

아이디어는 맞았으나 구현을 제대로 못해 해답을 찾아본 문제입니다.
구체적으로 visited 등에 ┌, ┐, └, ┘등 각 모양을 체크 후 재귀를 구현하는걸 세세히 코드화시키지 못하였습니다.
구현력 기르는 연습을 계속해야할 듯 합니다.

(5) 참고

참고 풀이1
참고 풀이2
참고 풀이3

1174__줄어드는 수 (Python)

0. 출처

1. 기록

  • 22/04/10 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 예제 입력과 예제 출력을 보고 뭔말인지 도저히 모르겠음
>> 문제 이해 함
>> 문제 조건에 맞는 1번째로 가장 작은수는 0
>> 2번째로 가장 작은 수는 1
>> 3번째로 가장 작은 수는 2
>> ...
>> 10번째로 가장 작은 수는 9
>> 11번째로 가장 작은 수는 10
>> 12번째로 가장 작은 수는 20

>> 그래서 어떻게 풀건데? 
>> 마지막 값 > 현재 값 경우, 재귀 진행하여 감소하는 수를 만들어 준다.
>> 감소하는 수를 정렬한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
sample

- 예제 출력 1 -
sample

(3) 코드

n = input()
arr = list()
result = list()

def dfs():
    if len(arr) > 0:
        result.append(int("".join(map(str, arr))))

    for i in range(0, 10):
        if len(arr) == 0 or arr[-1] > i:  # 마지막 값이 더 큰 경우
            arr.append(i)
            print(arr)
            dfs()
            arr.pop()

try:
    dfs()
    result.sort()
    print(result[n - 1])
except:
    print(-1)

(4) 정리

처음에 문제가 이해가 안가서 답안 코드에 1부터 하나하나 집어넣고 이해했다.

문제 이해력을 길러야겠다.

(5) 참고

참고 풀이

+ Recent posts