9372_상근이의 여행 (Python)

0. 출처

1. 기록

  • 22/04/18 (월)

2. 풀이

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

1. 아이디어
>> 

2. 시간복잡도
>>

3. 자료구조
>>

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

- 예제 입력 1 -
2 (테스트 케이스 수)
3 3 (국가의 수 / 비행기의 종류)
1 2
2 3
1 3
5 4 (국가의 수 / 비행기의 종류)
2 1
2 3
4 3
4 5

- 예제 출력 1 -
2
4

(3) 코드

sample

(4) 정리

문제를 잘 못읽어 예제입력 예제출력이 왜 저렇게되나 한참봤다..
왜 예제출력 결과가 2개나 나오는지 때문에.. (맨 처음에 주어진게 테스트 케이스였음)
문제를 잘 읽자

또한 모든 국가가 연결되어있기 때문에 모든 국가를 방문하려면 국가의 갯수 - 1 이 정답이다.

(5) 참고

참고 풀이

9934_완전 이진 트리 (Python)

0. 출처

1. 기록

  • 22/04/18 (월)

2. 풀이

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

1. 아이디어
>> 문제에서 주어진 방문순서는 중위 순회이다.
>> 레벨과 방문순서가 주어진다.
>> 주어진 것으로 트리의 정보를 구해야 한다.
>> 어떻게 구하지..?

>> 중위순회를 반대로 실행해야 한다.
>> level 활용하기
>> 중위순회 입력된 리스트 가운데가 항상 root 노드임을 활용하기
>> 중위 순회로 입력된 리스트를 왼쪽 부분 트리, 오른쪽 부분 트리로 쪼갤 줄 알아야한다.

2. 시간복잡도
>>

3. 자료구조
>>

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

- 예제 입력 1 -
2
2 1 3

- 예제 출력 1 -
1
2 3

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

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

(3) 코드

k = int(input())
inorder = list(map(int, input().split()))

answer = [[] for _ in range(k)]

def dfs(inorder, depth):

    # 트리의 root index를 찾아낸다.
    mid = (len(inorder) // 2)

    # 해당 깊이에 해당하는 node를 추가한다.
    answer[depth].append(inorder[mid])

    if len(inorder) == 1:
        return

    dfs(inorder[:mid], depth+1)
    dfs(inorder[mid+1:], depth+1)

dfs(inorder, 0)

for i in answer:
    print(*i)

(4) 정리

(5) 참고

참고 풀이

9934_[문제이름] (Python)

0. 출처

1. 기록

  • 22/04/18 (월)

2. 풀이

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

1. 아이디어
>> 문제에서 주어진 방문순서는 중위 순회이다.
>> 레벨과 방문순서가 주어진다.
>> 주어진 것으로 트리의 정보를 구해야 한다.
>> 어떻게 구하지..?

>> 중위순회를 반대로 실행해야 한다.

2. 시간복잡도
>>

3. 자료구조
>>

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

- 예제 입력 1 -
2
2 1 3

- 예제 출력 1 -
1
2 3

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

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

(3) 코드

sample

(4) 정리

(5) 참고

참고 풀이

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
참고 풀이

+ Recent posts