<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>동까의 코딩</title>
    <link>https://studycord.tistory.com/</link>
    <description>개발자로 성장하기 위해 공부 기록소입니다.
잘 부탁드립니다.... 많이 부족해요.</description>
    <language>ko</language>
    <pubDate>Thu, 23 Jul 2026 20:54:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>동까의 코딩</managingEditor>
    <image>
      <title>동까의 코딩</title>
      <url>https://tistory1.daumcdn.net/tistory/3810648/attach/74606865854644829385b719830a5903</url>
      <link>https://studycord.tistory.com</link>
    </image>
    <item>
      <title>[프로그래머스] 카카오 2022 공채 기출 - 파괴되지 않은 건물 python</title>
      <link>https://studycord.tistory.com/105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/92344&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760001343832&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kbSu6/hyZKDDl652/Eu6xk54ERI1JMy2Rdi5WL0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/sQ209/hyZLiFhR5z/lOHRKtraDHz3EGDxuCCb50/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92344&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kbSu6/hyZKDDl652/Eu6xk54ERI1JMy2Rdi5WL0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/sQ209/hyZLiFhR5z/lOHRKtraDHz3EGDxuCCb50/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[본 문제는 정확성과 효율성 테스트 각각 점수가 있는 문제입니다.] 라는 문구가 있는 걸 보고, 알고리즘으로 풀어야겠다는 마음을 먹게 되면서 효율성을 따지는 구현을 생각해보게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맵 크기가 N x M 크기로 주어지고, 항상 직사각형 모양으로 되어있고, 특정 좌표 두개가 주어지면 그 좌표들의 직사각형만큼 공격을 당하거나, 회복을 하는 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type, r1, c1, r2, c2, degree 가 주어지고, type 이 1이면 degree만큼 공격, 2면 degree만큼 회복되는 문제이고, 0보다 커야 파괴되지 않은 건물임에 포커스를 맞췄습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이 방법은 누적합을 알아보게 되었습니다. 계속해서 좌표들이 주어질 것이고, 모든 계산을 해준다면 시간초과가 날 것임이 확실했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 정확성과 효율성 테스트 각각 점수가 있다는게 아닐까..하는 추측입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차원 배열에 대한 누적합 문제를 생각하게 되었고, 가로, 세로 부분을 어떻게 더해주고, 어디에 누적합의 -를 해줄 지를 생각하면서 구현하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 r1, c1 좌표를 받으면 그 자리엔 type에 맞는 degree를 더해주고, 누적합을 빼줄 - 값을 좌표들의 벗어나는 곳에 주어져야 된다고 생각했습니다. 그래서 (r2 + 1, c1)과 (r1, c2 + 1) 좌표에 - 해주고, 각각의 - 좌표들의 누적합을 빼줄 수 있는 (r2 + 1, c2 + 1)에 그걸 상쇄시킬 수 있는 +를 해줘서 0의 균형을 맞춰주면 최종적으로 누적합의 조건을 맞출 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 소스코드는 그렇게 작성을 하고, 따로 board를 구성하여 기존의 board에 적용시켜 0보다 큰 것들만 answer 에 값에 count해줘서 답을 구할 수 있었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1760001533468&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(board, skill):
    answer = 0
    n, m = len(board), len(board[0])
    
    # board 누적합 해줄 수 있는 상황판 하나 만들어주기. 기존의 board 보다 1 더 크게
    sum_board = [[0 for _ in range(m + 1)] for _ in range(n + 1) ]
    
    # 누적합 해주는 코드 진행
    for a_type, r1, c1, r2, c2, degree in skill:
        if a_type == 1:
            val = -degree
        else:
            val = degree
        sum_board[r1][c1] += val
        sum_board[r2 + 1][c2 + 1] += val
        sum_board[r1][c2 + 1] -= val
        sum_board[r2 + 1][c1] -= val
        
    for i in range(n):
        for j in range(m):
            sum_board[i][j + 1] += sum_board[i][j]
    for j in range(m):
        for i in range(n):
            sum_board[i + 1][j] += sum_board[i][j]
    for i in range(n):
        for j in range(m):
            if sum_board[i][j] + board[i][j] &amp;gt; 0:
                answer += 1
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제를 풀면서 누적합에 대해 자세히 알게 되었고, 왜 써야 되는지를 많이 생각해보면서 문제를 풀게 되었습니다.&lt;/p&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>누적합</category>
      <category>카카오 기출</category>
      <category>파이썬</category>
      <category>프로그래머스 파괴되지 않는 건물</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/105</guid>
      <comments>https://studycord.tistory.com/105#entry105comment</comments>
      <pubDate>Thu, 9 Oct 2025 18:24:02 +0900</pubDate>
    </item>
    <item>
      <title>[코딩테스트 합격자 되기 파이썬] - 2주차 스터디 - BFS</title>
      <link>https://studycord.tistory.com/104</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. BFS(너비 우선 탐색) 알고리즘의 작동 원리를 설명하고, 어떤 자료구조를 사용하는지, 그리고 그 이유는 무엇인지 설명해주세요.&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS(너비 우선 탐색)는 그래프나 트리에서 시작 정점에서부터 인접한 노드를 먼저 방문하는 알고리즘입니다. BFS의 핵심 아이디어는 시작 정점으로부터 거리가 가까운 노드들을 먼저 처리하고, 그 다음 거리에 있는 노드들을 차례대로 탐색하는 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 BFS의 작동 원리를 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;시작 정점 선택:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;탐색의 출발점이 되는 정점을 선택합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;큐(Queue) 사용:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BFS에서는 FIFO(First-In, First-Out) 원칙을 따르는 큐를 사용합니다. 즉, 먼저 방문한 정점부터 처리하게 되어, 각 단계별(레벨별)로 노드를 확장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인접 노드 방문:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;현재 정점과 연결된 모든 인접 노드를 방문하고, 아직 방문하지 않은 노드를 큐에 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;큐가 빌 때까지 위 과정을 반복하여 모든 노드를 방문합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;자료구조로 큐를 사용하는 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;FIFO 특성:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;먼저 들어간 노드가 먼저 처리되므로, 각 레벨의 노드가 순서대로 방문되어 BFS가 레벨 순회 방식을 구현할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최단 경로 보장:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;무가중치 그래프에서 시작 정점으로부터 가장 짧은 경로를 탐색할 때 효과적입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;효율적인 방문 처리:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방문한 노드를 추적하기 위해 집합(set) 또는 방문 배열을 사용하여 중복 방문을 방지할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래는 파이썬 코드 예제와 함께 그래프 시각화를 통해 BFS를 구현한 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;import matplotlib.pyplot as plt
import networkx as nx
from collections import deque

# 그래프 시각화를 위한 그래프 생성
G = nx.Graph()
edges = [
    ('A', 'B'),
    ('A', 'C'),
    ('B', 'D'),
    ('B', 'E'),
    ('C', 'F'),
    ('C', 'G')
]
G.add_edges_from(edges)

# 위치 배치 및 그래프 시각화
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=800, font_size=12)
plt.title(&quot;BFS 탐색 대상 그래프&quot;)
plt.show()

# BFS 알고리즘 구현 함수
def bfs(graph, start):
    visited = set()         # 방문한 노드를 추적하기 위한 집합
    queue = deque([start])  # 시작 정점을 큐에 추가 (FIFO 성질 활용)
    order = []              # 방문 순서를 기록할 리스트
    
    while queue:
        node = queue.popleft()  # 큐의 가장 앞에 있는 노드를 추출
        if node not in visited:  # 아직 방문하지 않은 노드라면
            visited.add(node)  # 노드를 방문 처리
            order.append(node) # 방문 순서 기록
            # 현재 노드의 인접 노드들을 큐에 추가, 중복 방문 방지
            for neighbor in graph[node]:
                if neighbor not in visited:
                    queue.append(neighbor)
    return order

# 인접 리스트 형태의 간단한 그래프 정의
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F', 'G'],
    'D': ['B'],
    'E': ['B'],
    'F': ['C'],
    'G': ['C']
}

# BFS 탐색 실행 및 결과 출력
bfs_order = bfs(graph, 'A')
print(&quot;BFS 탐색 순서 (시작 정점 A부터):&quot;, bfs_order)
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 다음과 같은 과정을 거칩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;그래프 시각화:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;networkx&lt;span&gt;&amp;nbsp;&lt;/span&gt;라이브러리를 사용해 그래프를 생성하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;matplotlib로 시각화하여 BFS 탐색 대상의 전체 구조를 쉽게 파악할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BFS 함수:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;deque를 이용해 큐를 구현합니다.&lt;/li&gt;
&lt;li&gt;visited&lt;span&gt;&amp;nbsp;&lt;/span&gt;집합을 활용하여 이미 방문한 노드를 기록하고, 중복 처리를 방지합니다.&lt;/li&gt;
&lt;li&gt;큐에서 하나씩 노드를 꺼내고, 인접 노드를 방문하며 순서를 기록합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탐색 결과 출력:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BFS의 탐색 순서를 출력하여, 시작 정점 A부터 방문된 노드의 순서를 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이와 같이 BFS는 레벨 순서대로 정점을 방문하며, 큐 자료구조를 통해 효과적으로 탐색을 수행할 수 있습니다. 이 설명과 코드는 BFS의 작동 원리와 그 구현 방식을 충분히 상세히 다루고 있어, 알고리즘을 이해하는 데 큰 도움이 될 것입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. BFS와 DFS(깊이 우선 탐색)의 차이점은 무엇이며, 각각 어떤 종류의 문제에 더 적합한지 예시를 들어 설명해주세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS(너비 우선 탐색)와 DFS(깊이 우선 탐색)는 둘 다 그래프 탐색 알고리즘이지만, 탐색 방식과 사용 목적에 차이가 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;1. 탐색 방식의 차이&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;BFS (Breadth First Search):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;탐색 순서:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시작 정점에서부터 인접한 모든 정점을 먼저 방문한 후, 그 다음 단계(레벨)의 정점들을 차례대로 방문합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자료구조:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;FIFO(First-In, First-Out) 방식의 큐(Queue)를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특징:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레벨 순서대로 탐색하기 때문에, 무가중치 그래프에서 최단 경로를 찾는 데 유리합니다.&lt;/li&gt;
&lt;li&gt;탐색 경로가 넓게 확장되므로, 메모리 사용량이 많을 수 있습니다(특히 레벨이 높을 경우).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DFS (Depth First Search):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;탐색 순서:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시작 정점에서 한 방향으로 끝까지 깊이 내려간 후, 더 이상 진행할 수 없게 되면 이전 정점으로 돌아가 다른 경로를 탐색합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자료구조:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;LIFO(Last-In, First-Out) 특성을 가지는 스택(Stack) 또는 재귀 함수를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특징:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;경로를 따라 깊게 탐색하기 때문에, 특정 경로의 존재 여부를 빠르게 판단할 수 있습니다.&lt;/li&gt;
&lt;li&gt;전체 경로를 깊게 탐색하는 특성상, 경로 길이에 따라 스택 메모리 사용량이 증가할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. 문제 유형에 따른 적합성&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;BFS가 더 적합한 문제 예시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;최단 경로 탐색 (Shortest Path in Unweighted Graphs):&lt;/b&gt;&lt;br /&gt;BFS는 시작점에서부터의 거리를 레벨별로 탐색하기 때문에, 간선의 가중치가 없거나 동일한 경우 최단 경로를 쉽게 구할 수 있습니다.&lt;br /&gt;예시:&lt;span&gt;&amp;nbsp;&lt;/span&gt;미로 찾기에서 출발점부터 도착점까지 최소 이동 횟수를 구하는 문제.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레벨 순회 및 최단 거리 계산:&lt;/b&gt;&lt;br /&gt;네트워크나 소셜 미디어 연결 요소 분석 등에서, 특정 노드로부터의 거리에 따른 분석이 필요할 때 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;DFS가 더 적합한 문제 예시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;경로의 존재 여부 탐색:&lt;/b&gt;&lt;br /&gt;DFS는 특정 경로를 깊게 따라 탐색하기 때문에, 두 노드 간의 경로가 존재하는지 빠르게 판별할 수 있습니다.&lt;br /&gt;예시:&lt;span&gt;&amp;nbsp;&lt;/span&gt;사이클 찾기, 강한 연결 요소(scc) 탐색 등.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;백트래킹(Backtracking)을 이용한 문제:&lt;/b&gt;&lt;br /&gt;미로 탐색, 퍼즐 문제, 조합 및 순열 문제 등에서 한 경로를 선택해 끝까지 탐색한 후, 조건에 맞지 않으면 이전 단계로 돌아가 다른 경로를 시도할 때 DFS가 많이 활용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탑색 정렬(Topological Sort):&lt;/b&gt;&lt;br /&gt;방향성이 있는 그래프에서 순서를 결정할 때, DFS를 이용해 정렬을 수행하는 방식(DFS를 기반으로 한 위상 정렬)이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 간단한 파이썬 코드 예제&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래는 BFS와 DFS를 각각 구현한 파이썬 코드 예제로, 두 알고리즘의 차이점을 명확하게 보여줍니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;BFS 예제 (최단 경로 탐색 용도)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;from collections import deque

def bfs_shortest_path(graph, start, goal):
    # 큐에 (현재 정점, 경로)를 저장
    queue = deque([(start, [start])])
    visited = set()
    
    while queue:
        (vertex, path) = queue.popleft()
        if vertex in visited:
            continue
        visited.add(vertex)
        
        # 목표 정점에 도달했다면 경로 반환
        if vertex == goal:
            return path
        
        # 현재 정점의 인접 정점들을 탐색
        for neighbor in graph[vertex]:
            if neighbor not in visited:
                queue.append((neighbor, path + [neighbor]))
    return None

# 예제 그래프 (인접 리스트)
graph_example = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F', 'G'],
    'D': ['B'],
    'E': ['B', 'H'],
    'F': ['C'],
    'G': ['C'],
    'H': ['E']
}

print(&quot;BFS 최단 경로 (A -&amp;gt; H):&quot;, bfs_shortest_path(graph_example, 'A', 'H'))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;DFS 예제 (경로 존재 여부 및 깊이 탐색 용도)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;def dfs(graph, start, goal, path=None, visited=None):
    if path is None:
        path = [start]
    if visited is None:
        visited = set()
    
    visited.add(start)
    
    # 목표 정점에 도달하면 경로 반환
    if start == goal:
        return path
    
    for neighbor in graph[start]:
        if neighbor not in visited:
            result = dfs(graph, neighbor, goal, path + [neighbor], visited)
            if result is not None:
                return result
    return None

print(&quot;DFS 경로 탐색 (A -&amp;gt; H):&quot;, dfs(graph_example, 'A', 'H'))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;4. 결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;BFS와 DFS의 주요 차이점:&lt;/b&gt;&lt;br /&gt;BFS는 레벨 순서대로, 즉 가까운 노드부터 탐색하여 최단 경로를 보장하는 반면, DFS는 한 방향으로 깊게 탐색하는 알고리즘입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제에 따른 적합성:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최단 경로, 레벨 순회 등에는 BFS가 더 적합합니다.&lt;/li&gt;
&lt;li&gt;경로의 존재 여부 판별, 백트래킹 문제, 위상 정렬 등에는 DFS가 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제의 특성에 맞게 알고리즘을 선택하는 것이 중요한데, 예를 들어 무가중치 그래프에서 최단 경로를 구할 때는 BFS를, 특정 조건에 따른 모든 가능 경로를 탐색해야 할 때는 DFS를 선택하는 것이 일반적입니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. BFS 알고리즘의 시간 복잡도는 O(V + E)인데, 그래프의 형태(예: 밀집 그래프 vs 희소 그래프)가 실제 수행 시간에 어떤 영향을 미칠 수 있을지 설명해주세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 알고리즘의 시간 복잡도가 O(V + E)라는 것은, 알고리즘이 그래프의 모든 정점(V)과 모든 간선(E)을 한 번씩 처리한다는 의미입니다. 그러나 그래프의 형태에 따라 실제 수행 시간은 달라질 수 있습니다. 아래에서 밀집 그래프와 희소 그래프의 특성과, 이들이 BFS 수행 시간에 미치는 영향을 자세히 설명하겠습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 그래프의 종류: 밀집 그래프 vs 희소 그래프&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;밀집 그래프 (Dense Graph):&lt;/b&gt;&lt;br /&gt;밀집 그래프는 정점 간 연결된 간선 수가 많다는 특징을 가집니다. 일반적으로 정점의 수가 V일 때, 간선의 수 E는 최악의 경우 O(V&amp;sup2;)에 가까워집니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, V = 1000인 밀집 무방향 그래프에서 최대 간선 수는 약 500,000개가 될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;희소 그래프 (Sparse Graph):&lt;/b&gt;&lt;br /&gt;희소 그래프는 정점이 많더라도 간선의 수가 상대적으로 적은 그래프입니다. 일반적으로 간선의 수가 O(V) 정도인 경우가 많습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, V = 1000인 희소 그래프에서는 간선 수가 몇 천개 정도일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. BFS 실행 시간에 미치는 영향&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS의 시간 복잡도는 O(V + E)이므로, 실제 수행 시간은 V(정점 수)와 E(간선 수)에 따라 결정됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;밀집 그래프의 경우:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;간선 수가 매우 많음:&lt;/b&gt;&lt;br /&gt;밀집 그래프에서는 E의 값이 매우 커지기 때문에, BFS가 간선들을 처리하는 데 드는 시간이 전체 수행 시간의 대부분을 차지하게 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실제 시간:&lt;/b&gt;&lt;br /&gt;예를 들어, 밀집 그래프의 경우 간선 수가 O(V&amp;sup2;)라면, BFS의 시간 복잡도는 O(V + V&amp;sup2;)에서 사실상 O(V&amp;sup2;)로 표현할 수 있습니다.&lt;br /&gt;-&amp;gt; 결과적으로 정점 수가 커지면 수행 시간의 증가 폭이 기하급수적으로 커질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;희소 그래프의 경우:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;간선 수가 상대적으로 적음:&lt;/b&gt;&lt;br /&gt;희소 그래프에서는 간선의 수가 O(V)에 가깝기 때문에, 전체 BFS 수행 시간은 O(V + V) = O(V)로 보다 효율적으로 동작할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실제 시간:&lt;/b&gt;&lt;br /&gt;정점과 간선의 수가 적어, 많은 경우 BFS가 빠르게 실행됩니다. 특히, 정점 수가 많더라도 간선 수가 많지 않기 때문에, 처리해야 할 요소의 총 개수가 적어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 추가 고려 사항&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;상수 계수:&lt;/b&gt;&lt;br /&gt;알고리즘의 시간 복잡도 표현은 대수적 성장률을 나타내지만, 실제 구현에서는 자료구조 선택(예: 큐 구현에 사용하는 deque), 캐시 효율성, 메모리 접근 패턴 등 상수 계수가 실제 실행 시간에 영향을 줄 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;밀집 그래프의 경우, 많은 간선을 처리해야 하므로 상수 계수의 영향이 더 뚜렷할 수 있습니다.&lt;/li&gt;
&lt;li&gt;희소 그래프에서는 이러한 영향이 상대적으로 미미할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리 사용:&lt;/b&gt;&lt;br /&gt;밀집 그래프에서는 많은 간선을 저장해야 하므로 메모리 사용량이 증가하며, 메모리 접근 비용이 BFS 수행 시간에 추가적인 영향을 줄 수 있습니다.&lt;br /&gt;반면, 희소 그래프는 메모리 요구량이 적어 이러한 문제가 덜 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. 결론&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS 알고리즘의 이론적 시간 복잡도는 O(V + E)로 정의되어 있으며, 이론적으로는 모든 그래프에 동일하게 적용됩니다. 하지만 실제 수행 시간은 그래프의 형태에 따라 크게 달라질 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;밀집 그래프에서는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;간선의 수가 매우 많기 때문에 처리 시간의 대부분을 간선 탐색에 할애하게 되어, 성능이 저하될 가능성이 높습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;희소 그래프에서는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;간선의 수가 적기 때문에, BFS가 빠르게 동작할 수 있으며, 전체 수행 시간도 비교적 짧습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서, 문제에서 다루는 그래프의 특성을 고려하여 알고리즘 선택이나 최적화 방법을 결정하는 것이 중요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. 문제풀이&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;1. 게임 맵 최단거리&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://studycord.tistory.com/103&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://studycord.tistory.com/103&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1744553811015&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[python] 프로그래머스 - 게임 맵 최단거리&quot; data-og-description=&quot;파이썬 프로그래머스 - 게임 맵 최단거리문제 설명프로그래머스의 게임 맵 최단거리 문제는 직사각형 모양의 맵에서 시작점(0, 0)에서 도착점(n-1, m-1)까지 이동할 때 거쳐야 하는 최소 칸 수를 구&quot; data-og-host=&quot;studycord.tistory.com&quot; data-og-source-url=&quot;https://studycord.tistory.com/103&quot; data-og-url=&quot;https://studycord.tistory.com/103&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/diXNRB/hyYB7tk5eS/5LGe884s2JG3oKXmifrfT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/f4QRs/hyYCiO88hQ/O8KCQyNFgr6p4VKvY1ElBk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/DmhdT/hyYCcBot2r/LQ7vACQQB73ZHgK6gNXYO1/img.jpg?width=3024&amp;amp;height=4032&amp;amp;face=0_0_3024_4032&quot;&gt;&lt;a href=&quot;https://studycord.tistory.com/103&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://studycord.tistory.com/103&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/diXNRB/hyYB7tk5eS/5LGe884s2JG3oKXmifrfT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/f4QRs/hyYCiO88hQ/O8KCQyNFgr6p4VKvY1ElBk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/DmhdT/hyYCcBot2r/LQ7vACQQB73ZHgK6gNXYO1/img.jpg?width=3024&amp;amp;height=4032&amp;amp;face=0_0_3024_4032');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[python] 프로그래머스 - 게임 맵 최단거리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;파이썬 프로그래머스 - 게임 맵 최단거리문제 설명프로그래머스의 게임 맵 최단거리 문제는 직사각형 모양의 맵에서 시작점(0, 0)에서 도착점(n-1, m-1)까지 이동할 때 거쳐야 하는 최소 칸 수를 구&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;studycord.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;2. 경주로 건설&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;돌아오는 주에 추가적으로 풀어보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;시뮬레이션 문제만 풀다보니 미뤄뒀던 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 회고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 오늘 삼성 코딩테스트를 보고 왔습니다. 꾸준히 뭔가를 한다는 것이 정말 필요한 것임을 느끼게 되었습니다. 긴장하고, 초조해하다보니 알고 있다고 생각한 부분도 알 수 없고, 잔잔한 실수들도 많이 나왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 시간 복잡도를 계산하면서 푸는 연습을 진행해야겠습니다. (실제 시험에서 매우 중요한 것을 느꼈습니다.....)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 메모리관리, 시간 설정하고 문제풀이, 일정 기간 후 다시 문제 풀어보기 등 다양한 방법을 활용하면서 꾸준히 나아가겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <category>꾸준히!</category>
      <category>더 열심히 하겠습니다</category>
      <category>박경록 저자 스터디</category>
      <category>코딩테스트</category>
      <category>코딩테스트 합격자 되기 파이썬 스터디</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/104</guid>
      <comments>https://studycord.tistory.com/104#entry104comment</comments>
      <pubDate>Sun, 13 Apr 2025 23:20:24 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 게임 맵 최단거리</title>
      <link>https://studycord.tistory.com/103</link>
      <description>&lt;h1&gt;파이썬 &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1844&quot;&gt;프로그래머스&lt;/a&gt; - 게임 맵 최단거리&lt;/h1&gt;
&lt;h2&gt;문제 설명&lt;/h2&gt;
&lt;p&gt;프로그래머스의 &lt;strong&gt;게임 맵 최단거리&lt;/strong&gt; 문제는 직사각형 모양의 맵에서 시작점(0, 0)에서 도착점(n-1, m-1)까지 이동할 때 거쳐야 하는 최소 칸 수를 구하는 문제입니다.&lt;br&gt;맵은 &lt;code&gt;1&lt;/code&gt;과 &lt;code&gt;0&lt;/code&gt;으로 구성되며, &lt;code&gt;1&lt;/code&gt;은 이동할 수 있는 칸, &lt;code&gt;0&lt;/code&gt;은 이동할 수 없는 칸을 나타냅니다.&lt;br&gt;상하좌우 방향으로만 이동할 수 있으며, 시작점과 도착점은 항상 &lt;code&gt;1&lt;/code&gt;입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;문제 접근 방식&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;BFS(너비 우선 탐색) 활용&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;시작점에서 출발하여 도착점까지 도달하는 경로 중, 가장 짧은 경로를 찾아내기 위해 BFS를 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;방문 처리&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;방문한 칸을 추적하여 중복 방문을 방지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;거리 기록&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;현재까지 이동한 거리를 &lt;code&gt;maps&lt;/code&gt; 배열에 기록하여, 각 칸에 도달하는 데 필요한 최소 이동 횟수를 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;종료 조건&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;도착점에 도달하면, 현재 이동 거리에서 1을 더한 값(마지막 칸 포함)을 반환합니다.&lt;/li&gt;
&lt;li&gt;도착할 수 없는 경우 &lt;code&gt;-1&lt;/code&gt;을 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;문제 풀이&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;from collections import deque

def solution(maps):
    answer = 0
    # n: 행의 수, m: 열의 수
    n, m = len(maps), len(maps[0])
    # 도착점 좌표
    f_x, f_y = n - 1, m - 1

    # 동, 서, 남, 북 이동 방향
    dx = [0, 0, 1, -1]
    dy = [1, -1, 0, 0]

    # 방문 여부를 표시할 배열 초기화 (모든 칸은 미방문 상태)
    visited = [[False] * m for _ in range(n)]
    visited[0][0] = True

    # BFS를 위한 큐 초기화
    queue = deque()
    queue.append((0, 0))

    while queue:
        x, y = queue.popleft()

        # 상하좌우 방향 탐색
        for i in range(4):
            xx = x + dx[i]
            yy = y + dy[i]

            # 맵의 범위 체크: 범위를 벗어나면 무시
            if xx &amp;lt; 0 or xx &amp;gt;= n or yy &amp;lt; 0 or yy &amp;gt;= m:
                continue

            # 도착 지점인 경우, 현재 칸의 값에 1을 더해 최단 거리를 반환
            if xx == f_x and yy == f_y:
                answer = maps[x][y] + 1
                return answer

            # 이동 가능하고 미방문한 칸인 경우 처리
            if not visited[xx][yy] and maps[xx][yy] == 1:
                queue.append((xx, yy))
                visited[xx][yy] = True
                # 다음 칸까지의 이동 거리를 기록 (현재 칸 값 + 1)
                maps[xx][yy] = maps[x][y] + 1

    # 도착점에 도달하지 못한 경우 -1 반환
    answer = -1
    return answer&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;구현 시 주의사항 및 팁&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;BFS 활용:&lt;ul&gt;
&lt;li&gt;BFS를 사용하면 시작점에서 도착점까지의 최단 경로를 찾을 수 있으므로, 경로의 이동 횟수를 효과적으로 계산할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;방문 처리:&lt;ul&gt;
&lt;li&gt;visited 배열을 이용해 이미 방문한 칸은 중복 방문하지 않도록 하여, 불필요한 탐색을 막습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;거리 기록:&lt;ul&gt;
&lt;li&gt;maps 배열에 현재까지 이동한 거리 정보를 갱신하면, 별도의 추가 배열 없이도 각 칸까지의 최단 경로 길이를 파악할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;경계 조건 처리:&lt;ul&gt;
&lt;li&gt;맵의 범위를 벗어나는 경우를 반드시 체크하여, 인덱스 에러를 예방하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;경로 미도달 시 처리:&lt;ul&gt;
&lt;li&gt;모든 가능한 경로를 탐색한 후에도 도착점에 도달하지 못할 경우, -1을 반환해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>BFS</category>
      <category>python 게임 맵 최단거리</category>
      <category>게임 맵 최단거리 파이썬</category>
      <category>스터디</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/103</guid>
      <comments>https://studycord.tistory.com/103#entry103comment</comments>
      <pubDate>Sun, 13 Apr 2025 23:13:22 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 양과 늑대</title>
      <link>https://studycord.tistory.com/102</link>
      <description>&lt;h1&gt;파이썬 [프로그래머스] - 양과 늑대&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 설명&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;양과 늑대&quot; 문제는 트리 형태로 구성된 노드에서 양과 늑대가 존재하는 상황에서, 루트 노드부터 시작해 이동하면서&lt;br /&gt;최대한 많은 양을 구하는 문제입니다. 각 노드는 0(양)과 1(늑대)로 표시되며, 이동 중 언제나 양의 수가 늑대의 수보다 많아야 합니다.&lt;br /&gt;문제의 목표는 가능한 경로들 중, 조건을 만족하면서 최대한 많은 양을 모으는 경우의 양의 수를 구하는 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 접근 방식&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DFS(깊이 우선 탐색) 활용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드들을 깊이 우선 탐색하면서 현재까지 모은 양(sheeps)과 늑대(wolves)의 수를 관리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방문 배열 사용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 노드의 방문 여부를 추적하여 중복 방문을 방지하고, 다른 경로 탐색을 위해 방문 상태를 초기화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;조건 검사&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DFS 내에서 매번 &lt;code&gt;sheeps &amp;gt; wolves&lt;/code&gt; 조건을 확인하여, 조건을 만족할 때만 경로를 확장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;간선 탐색&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미 방문한 부모 노드와 연결된 아직 방문하지 않은 자식 노드를 대상으로 DFS를 수행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 저장 및 반환&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;탐색 과정 중 가능한 모든 경로의 양의 수를 기록한 후, 그 중 최댓값을 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 풀이&lt;/h2&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def solution(info, edges):
    answer = []
    visited = [False] * len(info)

    def dfs(sheeps, wolves):
        # 현재까지 모은 양이 늑대보다 많으면 경로 유지, 그렇지 않으면 탐색 중단
        if sheeps &amp;gt; wolves:
            answer.append(sheeps)
        else:
            return

        # 모든 간선을 순회하며 이동 가능한 경로 탐색
        for p, c in edges:
            # 부모 노드 p는 방문했으나, 자식 노드 c는 아직 방문하지 않은 경우에만 진행
            if visited[p] and not visited[c]:
                visited[c] = True
                if info[c] == 0:  # 양인 경우
                    dfs(sheeps + 1, wolves)
                else:           # 늑대인 경우
                    dfs(sheeps, wolves + 1)
                # 다른 경로 탐색을 위해 방문 상태 초기화
                visited[c] = False

    # 루트 노드(0번)는 시작점이므로 방문 처리
    visited[0] = True
    dfs(1, 0)

    return max(answer)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구현 시 주의사항 및 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방문 배열 관리:&lt;br /&gt;DFS 탐색 중에 노드를 방문한 후, 다른 경로를 탐색할 수 있도록 재귀 호출이 끝난 후 방문 상태를 False로 되돌리는 것이 중요합니다.&lt;/li&gt;
&lt;li&gt;조건 검사:&lt;br /&gt;각 DFS 호출에서 현재까지 모은 양이 늑대보다 많아야만 탐색을 이어갑니다.&lt;br /&gt;조건을 만족하지 못하면 더 이상 진행하지 않고 탐색을 종료합니다.&lt;/li&gt;
&lt;li&gt;간선 탐색:&lt;br /&gt;모든 간선을 순회하여, 부모 노드가 방문된 상태에서 자식 노드가 아직 방문되지 않은 경우에만 DFS를 진행합니다.&lt;/li&gt;
&lt;li&gt;결과 저장:&lt;br /&gt;각 경로마다 모을 수 있는 양의 수를 answer 리스트에 기록하고, 최종적으로 이 중 최댓값을 반환합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>dfs</category>
      <category>양과 늑대</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/102</guid>
      <comments>https://studycord.tistory.com/102#entry102comment</comments>
      <pubDate>Sun, 6 Apr 2025 23:57:56 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 네트워크</title>
      <link>https://studycord.tistory.com/101</link>
      <description>&lt;h1&gt;파이썬 [프로그래머스] - 네트워크&lt;/h1&gt;
&lt;h2&gt;문제 설명&lt;/h2&gt;
&lt;p&gt;프로그래머스의 &lt;strong&gt;네트워크&lt;/strong&gt; 문제는 여러 컴퓨터가 연결되어 있는 네트워크의 개수를 구하는 문제입니다.&lt;br&gt;컴퓨터들의 연결 정보는 2차원 리스트(인접 행렬)로 주어지며,&lt;br&gt;연결된 컴퓨터들은 하나의 네트워크를 구성합니다.&lt;br&gt;문제의 목표는 주어진 컴퓨터들의 연결 정보로부터 &lt;strong&gt;총 네트워크의 개수&lt;/strong&gt;를 찾는 것입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;문제 접근 방식&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;방문 배열(visit) 생성&lt;/strong&gt;  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 컴퓨터가 이미 네트워크 탐색에 포함되었는지 확인하기 위해 &lt;code&gt;visit&lt;/code&gt; 리스트를 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;깊이 우선 탐색(DFS) 활용&lt;/strong&gt;  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;한 컴퓨터에서 시작하여 연결된 모든 컴퓨터들을 재귀적으로 탐색합니다.&lt;/li&gt;
&lt;li&gt;탐색 중 방문한 컴퓨터는 &lt;code&gt;visit&lt;/code&gt; 리스트를 통해 중복 방문을 방지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;네트워크 수 카운팅&lt;/strong&gt;  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;아직 방문하지 않은 컴퓨터가 발견되면 DFS를 실행하고, 새로운 네트워크로 간주하여 카운트를 증가시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;문제 풀이&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(n, computers):
    answer = 0
    visit = [False] * n

    def dfs(i):
        visit[i] = True
        print(&amp;#39;i : &amp;#39;, i)
        # 현재 컴퓨터 i와 연결된 다른 컴퓨터 j를 확인
        for j in range(i+1, n):
            print(&amp;#39;j : &amp;#39;, j)
            if computers[i][j] == 1:
                dfs(j)

    for i in range(n):
        if not visit[i]:
            dfs(i)
            answer += 1
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;주의사항 및 팁&lt;/h2&gt;
&lt;p&gt;방문 여부 확인:&lt;br&gt;DFS 함수 내에서 방문 여부를 체크하여 무한 재귀나 중복 방문을 피해야 합니다.&lt;br&gt;인접 행렬 탐색:&lt;br&gt;현재 코드는 for j in range(i+1, n):로 진행되는데,&lt;br&gt;이는 i보다 큰 인덱스의 컴퓨터만 확인하므로,&lt;br&gt;문제 조건(대칭 행렬, 자기 자신 포함)에서 올바르게 동작하는지 확인이 필요합니다. 일반적인 경우에는 모든 j에 대해 검사(for j in range(n):)하고,&lt;br&gt;if computers[i][j] == 1 and not visit[j]:와 같이 방문 여부를 함께 체크하는 것이 안전합니다.&lt;br&gt;디버깅 출력 제거:&lt;br&gt;최종 제출 시에는 print() 문을 제거하여 디버깅 출력 없이 실행하도록 합니다.&lt;/p&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>dfs</category>
      <category>네트워크</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/101</guid>
      <comments>https://studycord.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 6 Apr 2025 23:55:41 +0900</pubDate>
    </item>
    <item>
      <title>[코딩테스트 합격자 되기 파이썬] 1주차 스터디 - DFS</title>
      <link>https://studycord.tistory.com/100</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DFS를 구현하는 대표적인 두 가지 방법은 재귀 호출을 이용하는 것과 명시적인 스택(Stack) 자료구조를 사용하는 것입니다. 각 구현 방식의 장단점을 비교 설명해주세요&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;127&quot; data-start=&quot;106&quot; data-ke-size=&quot;size16&quot;&gt;1. 재귀 호출을 이용한 DFS&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;136&quot; data-start=&quot;129&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;299&quot; data-start=&quot;137&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;230&quot; data-start=&quot;137&quot;&gt;&lt;b&gt;간결하고 직관적&lt;/b&gt;: 재귀 호출을 사용하면 코드가 간단해지고, DFS의 기본 개념(현재 노드에서 다음 노드로 자연스럽게 진행)을 직관적으로 표현할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;299&quot; data-start=&quot;231&quot;&gt;&lt;b&gt;내장 스택 활용&lt;/b&gt;: 프로그래밍 언어의 함수 호출 스택을 활용하기 때문에 별도의 자료구조를 구현할 필요가 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;308&quot; data-start=&quot;301&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;517&quot; data-start=&quot;309&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;370&quot; data-start=&quot;309&quot;&gt;&lt;b&gt;스택 오버플로우 위험&lt;/b&gt;: 탐색 깊이가 매우 깊거나 그래프가 크면 함수 호출 스택이 넘칠 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;459&quot; data-start=&quot;371&quot;&gt;&lt;b&gt;제어의 한계&lt;/b&gt;: 재귀 과정 중에 스택 상태를 직접 제어하기 어렵기 때문에, 특정 상황에서 세밀한 제어가 필요한 경우에는 유연성이 떨어질 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;517&quot; data-start=&quot;460&quot;&gt;&lt;b&gt;디버깅 어려움&lt;/b&gt;: 재귀 호출이 복잡해지면 호출 스택을 추적하며 디버깅하기 어려울 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;522&quot; data-start=&quot;519&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;547&quot; data-start=&quot;524&quot; data-ke-size=&quot;size16&quot;&gt;2. 명시적인 스택을 이용한 DFS&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;556&quot; data-start=&quot;549&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;810&quot; data-start=&quot;557&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;652&quot; data-start=&quot;557&quot;&gt;&lt;b&gt;스택 오버플로우 회피&lt;/b&gt;: 직접 스택 자료구조를 관리하므로, 재귀 호출에 비해 스택의 크기를 유연하게 조절할 수 있으며, 스택 오버플로우 위험을 줄일 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;718&quot; data-start=&quot;653&quot;&gt;&lt;b&gt;세밀한 제어&lt;/b&gt;: 스택의 동작을 직접 관리할 수 있어, 탐색 순서나 조건을 더욱 세밀하게 조정할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;810&quot; data-start=&quot;719&quot;&gt;&lt;b&gt;반복문 기반 구현&lt;/b&gt;: 반복문을 활용하기 때문에, 재귀 호출의 오버헤드(함수 호출 비용)를 줄일 수 있고, 일부 언어에서는 성능 면에서 유리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;819&quot; data-start=&quot;812&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;965&quot; data-start=&quot;820&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;891&quot; data-start=&quot;820&quot;&gt;&lt;b&gt;코드 복잡도 증가&lt;/b&gt;: 명시적으로 스택을 구현하고 관리해야 하므로, 코드가 재귀 방식에 비해 다소 복잡해질 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;965&quot; data-start=&quot;892&quot;&gt;&lt;b&gt;가독성 저하&lt;/b&gt;: DFS의 기본 개념은 동일하지만, 스택 자료구조를 사용하는 구현은 재귀 방식보다 읽기 어려울 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;970&quot; data-start=&quot;967&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;978&quot; data-start=&quot;972&quot; data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;1133&quot; data-start=&quot;980&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1048&quot; data-start=&quot;980&quot;&gt;&lt;b&gt;재귀 호출 방식&lt;/b&gt;은 코드가 간결하고 이해하기 쉽지만, 탐색 깊이가 깊어질 경우 스택 오버플로우의 위험이 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1133&quot; data-start=&quot;1049&quot;&gt;&lt;b&gt;명시적인 스택 방식&lt;/b&gt;은 스택 오버플로우 문제를 회피할 수 있고, 더 세밀한 제어가 가능하지만, 구현이 복잡해지고 가독성이 떨어질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;방향 그래프(Directed Graph)에서 사이클(Cycle) 존재 여부를 판별하기 위해 DFS를 어떻게 활용할 수 있는지 구체적인 알고리즘을 설명해주세요&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;121&quot; data-start=&quot;107&quot; data-ke-size=&quot;size16&quot;&gt;1. 기본 아이디어&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;172&quot; data-start=&quot;123&quot; data-ke-size=&quot;size16&quot;&gt;DFS를 수행하면서 각 노드의 방문 상태를 관리하는데, 두 가지 주요 정보를 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;307&quot; data-start=&quot;174&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;227&quot; data-start=&quot;174&quot;&gt;&lt;b&gt;방문 여부 (visited):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해당 노드를 한 번이라도 방문했는지 여부를 표시합니다.&lt;/li&gt;
&lt;li data-end=&quot;307&quot; data-start=&quot;228&quot;&gt;&lt;b&gt;재귀 호출 스택 (recursion stack) 또는 현재 경로 (path):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;현재 DFS 호출 경로에 포함된 노드들을 추적합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;426&quot; data-start=&quot;309&quot; data-ke-size=&quot;size16&quot;&gt;방향 그래프에서는 사이클이 존재하면 DFS 도중 이미 현재 경로에 있는 노드를 다시 방문하게 됩니다. 이 때, 만약 현재 DFS 경로에 포함된 노드를 다시 만나면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사이클이 존재한다&lt;/b&gt;고 판단할 수 있습니다.&lt;/p&gt;
&lt;hr data-end=&quot;431&quot; data-start=&quot;428&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;447&quot; data-start=&quot;433&quot; data-ke-size=&quot;size16&quot;&gt;2. 알고리즘 단계&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-end=&quot;1184&quot; data-start=&quot;449&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;449&quot;&gt;&lt;b&gt;초기화:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;585&quot; data-start=&quot;464&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;507&quot; data-start=&quot;464&quot;&gt;모든 노드에 대해&lt;span&gt;&amp;nbsp;&lt;/span&gt;visited[node] = False로 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;511&quot;&gt;모든 노드에 대해&lt;span&gt;&amp;nbsp;&lt;/span&gt;recStack[node] = False로 설정합니다. (또는 재귀 호출 중인 경로를 추적할 자료구조 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;646&quot; data-start=&quot;587&quot;&gt;&lt;b&gt;모든 노드에 대해 DFS 실행:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;646&quot; data-start=&quot;615&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;646&quot; data-start=&quot;615&quot;&gt;아직 방문하지 않은 노드에 대해 DFS를 호출합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;648&quot;&gt;&lt;b&gt;DFS 함수 내부:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1095&quot; data-start=&quot;669&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;711&quot; data-start=&quot;669&quot;&gt;현재 노드를 방문 상태로 표시:&lt;span&gt;&amp;nbsp;&lt;/span&gt;visited[node] = True&lt;/li&gt;
&lt;li data-end=&quot;762&quot; data-start=&quot;715&quot;&gt;현재 노드를 재귀 스택(경로)에 추가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;recStack[node] = True&lt;/li&gt;
&lt;li data-end=&quot;977&quot; data-start=&quot;766&quot;&gt;현재 노드와 인접한 모든 이웃 노드에 대해 다음을 수행:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;977&quot; data-start=&quot;805&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;855&quot; data-start=&quot;805&quot;&gt;만약 이웃 노드가 아직 방문하지 않았다면, 해당 노드에 대해 DFS를 재귀 호출합니다.&lt;/li&gt;
&lt;li data-end=&quot;904&quot; data-start=&quot;861&quot;&gt;재귀 호출 결과 사이클이 검출되면, 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사이클 존재&lt;/b&gt;를 반환합니다.&lt;/li&gt;
&lt;li data-end=&quot;977&quot; data-start=&quot;910&quot;&gt;만약 이웃 노드가 이미 방문되었고, 동시에 현재 DFS 경로(재귀 스택)에 있다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사이클이 검출된 것&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1046&quot; data-start=&quot;981&quot;&gt;현재 노드에 대한 모든 처리가 끝나면, DFS 경로에서 노드를 제거:&lt;span&gt;&amp;nbsp;&lt;/span&gt;recStack[node] = False&lt;/li&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;1050&quot;&gt;사이클이 발견되지 않으면 DFS 함수를 종료하며, 사이클이 없음을 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1184&quot; data-start=&quot;1097&quot;&gt;&lt;b&gt;결과 반환:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1184&quot; data-start=&quot;1114&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1184&quot; data-start=&quot;1114&quot;&gt;모든 DFS 호출이 완료된 후에도 사이클이 한 번도 검출되지 않았다면, 해당 그래프는 사이클이 없는 것으로 결론 내립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-end=&quot;1189&quot; data-start=&quot;1186&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;1214&quot; data-start=&quot;1191&quot; data-ke-size=&quot;size16&quot;&gt;3. 의사코드(Pseudocode)&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;python&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;isCyclic&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;/span&gt;&lt;span&gt;): &lt;/span&gt;&lt;span&gt;&lt;span&gt;# graph: 각 노드와 인접 노드들의 리스트(또는 딕셔너리)&lt;/span&gt;&lt;/span&gt;&lt;span&gt; visited = {node: &lt;/span&gt;&lt;span&gt;&lt;span&gt;False&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; node &lt;/span&gt;&lt;span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graph} recStack = {node: &lt;/span&gt;&lt;span&gt;&lt;span&gt;False&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; node &lt;/span&gt;&lt;span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graph} &lt;/span&gt;&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;dfs&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;node&lt;/span&gt;&lt;/span&gt;&lt;span&gt;): visited[node] = &lt;/span&gt;&lt;span&gt;&lt;span&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span&gt; recStack[node] = &lt;/span&gt;&lt;span&gt;&lt;span&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; neighbor &lt;/span&gt;&lt;span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graph[node]: &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;not&lt;/span&gt;&lt;/span&gt;&lt;span&gt; visited[neighbor]: &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; dfs(neighbor): &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;elif&lt;/span&gt;&lt;/span&gt;&lt;span&gt; recStack[neighbor]: &lt;/span&gt;&lt;span&gt;&lt;span&gt;# 현재 경로에 이미 포함된 노드를 다시 방문&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span&gt; recStack[node] = &lt;/span&gt;&lt;span&gt;&lt;span&gt;False&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;False&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; node &lt;/span&gt;&lt;span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graph: &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;not&lt;/span&gt;&lt;/span&gt;&lt;span&gt; visited[node]: &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; dfs(node): &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;# 사이클 존재&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;False&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;# 사이클 없음&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1914&quot; data-start=&quot;1911&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;1930&quot; data-start=&quot;1916&quot; data-ke-size=&quot;size16&quot;&gt;4. 알고리즘 설명&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;2231&quot; data-start=&quot;1932&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2037&quot; data-start=&quot;1932&quot;&gt;&lt;b&gt;재귀 스택 활용:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DFS의 재귀 호출 중에&lt;span&gt;&amp;nbsp;&lt;/span&gt;recStack을 통해 현재 탐색 경로에 있는 노드를 추적합니다. 이때, 경로에 있는 노드를 다시 방문하면 사이클이 있는 것입니다.&lt;/li&gt;
&lt;li data-end=&quot;2127&quot; data-start=&quot;2038&quot;&gt;&lt;b&gt;방문 여부 관리:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;visited&lt;span&gt;&amp;nbsp;&lt;/span&gt;배열을 사용하여 이미 방문한 노드를 다시 DFS 호출하지 않도록 하여, 중복 탐색을 방지하고 성능을 최적화합니다.&lt;/li&gt;
&lt;li data-end=&quot;2186&quot; data-start=&quot;2128&quot;&gt;&lt;b&gt;시간 복잡도:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;모든 노드와 간선을 한 번씩 탐색하기 때문에, 시간 복잡도는 O(V+E)입니다.&lt;/li&gt;
&lt;li data-end=&quot;2231&quot; data-start=&quot;2187&quot;&gt;&lt;b&gt;공간 복잡도:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방문 배열과 재귀 스택에 O(V)의 공간이 필요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;재귀를 활용한 DFS에서 가장 최근의 노드로 돌아가는 백트래킹 동작이 어떤 방식으로 동작하는지 하나의 예를 들어 설명해주세요&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DFS(깊이 우선 탐색)에서 재귀 호출로 탐색을 진행할 때, 더 이상 진행할 수 없거나 모든 인접 노드를 방문한 경우에는 현재 호출된 함수가 종료되면서 바로 이전의 호출(즉, 부모 노드의 탐색)으로 돌아가게 됩니다. 이를 백트래킹(backtracking)이라고 부릅니다. 아래 예시를 통해 구체적으로 설명드리겠습니다.&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;343&quot; data-start=&quot;263&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;288&quot; data-start=&quot;263&quot;&gt;&lt;b&gt;노드 A&lt;/b&gt;의 인접 노드: B, C&lt;/li&gt;
&lt;li data-end=&quot;311&quot; data-start=&quot;289&quot;&gt;&lt;b&gt;노드 B&lt;/b&gt;의 인접 노드: D&lt;/li&gt;
&lt;li data-end=&quot;343&quot; data-start=&quot;312&quot;&gt;&lt;b&gt;노드 C&lt;/b&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;노드 D&lt;/b&gt;는 인접 노드가 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;348&quot; data-start=&quot;345&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;373&quot; data-start=&quot;350&quot; data-ke-size=&quot;size16&quot;&gt;DFS 재귀 호출 및 백트래킹 과정&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-end=&quot;1095&quot; data-start=&quot;375&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;460&quot; data-start=&quot;375&quot;&gt;&lt;b&gt;시작: DFS(A) 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;460&quot; data-start=&quot;399&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;414&quot; data-start=&quot;399&quot;&gt;&lt;b&gt;A&lt;/b&gt;를 방문합니다.&lt;/li&gt;
&lt;li data-end=&quot;460&quot; data-start=&quot;418&quot;&gt;&lt;b&gt;A&lt;/b&gt;의 첫 번째 인접 노드인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;B&lt;/b&gt;로 DFS 호출을 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;538&quot; data-start=&quot;462&quot;&gt;&lt;b&gt;DFS(B) 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;538&quot; data-start=&quot;482&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;497&quot; data-start=&quot;482&quot;&gt;&lt;b&gt;B&lt;/b&gt;를 방문합니다.&lt;/li&gt;
&lt;li data-end=&quot;538&quot; data-start=&quot;501&quot;&gt;&lt;b&gt;B&lt;/b&gt;의 인접 노드인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;D&lt;/b&gt;로 DFS 호출을 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;719&quot; data-start=&quot;540&quot;&gt;&lt;b&gt;DFS(D) 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;719&quot; data-start=&quot;560&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;575&quot; data-start=&quot;560&quot;&gt;&lt;b&gt;D&lt;/b&gt;를 방문합니다.&lt;/li&gt;
&lt;li data-end=&quot;645&quot; data-start=&quot;579&quot;&gt;&lt;b&gt;D&lt;/b&gt;는 인접 노드가 없으므로, DFS(D)는 더 이상 진행할 노드가 없다고 판단하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수를 종료&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li data-end=&quot;719&quot; data-start=&quot;649&quot;&gt;&lt;b&gt;함수 종료&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시점에서 DFS는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;D&lt;/b&gt;의 호출 스택을 제거(백트래킹)하고, 호출했던 부모인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;B&lt;/b&gt;로 돌아갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;861&quot; data-start=&quot;721&quot;&gt;&lt;b&gt;백트래킹 후 DFS(B)로 복귀&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;861&quot; data-start=&quot;749&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;791&quot; data-start=&quot;749&quot;&gt;DFS(B)는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;D&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;외에 더 방문할 인접 노드가 있는지 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;861&quot; data-start=&quot;795&quot;&gt;만약 다른 인접 노드가 없다면, DFS(B) 역시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;함수를 종료&lt;/b&gt;하고, 호출했던 부모인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;A&lt;/b&gt;로 돌아갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;967&quot; data-start=&quot;863&quot;&gt;&lt;b&gt;백트래킹 후 DFS(A)로 복귀&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;967&quot; data-start=&quot;891&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;940&quot; data-start=&quot;891&quot;&gt;DFS(A)는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;B&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;외에 다른 인접 노드인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;C&lt;/b&gt;가 남아 있음을 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;967&quot; data-start=&quot;944&quot;&gt;&lt;b&gt;C&lt;/b&gt;로 DFS 호출을 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;969&quot;&gt;&lt;b&gt;DFS(C) 호출&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1095&quot; data-start=&quot;989&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1004&quot; data-start=&quot;989&quot;&gt;&lt;b&gt;C&lt;/b&gt;를 방문합니다.&lt;/li&gt;
&lt;li data-end=&quot;1044&quot; data-start=&quot;1008&quot;&gt;&lt;b&gt;C&lt;/b&gt;는 인접 노드가 없으므로, DFS(C)는 종료됩니다.&lt;/li&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;1048&quot;&gt;DFS는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;C&lt;/b&gt;의 호출 스택을 제거하고, 최종적으로 DFS(A)도 종료됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-end=&quot;1100&quot; data-start=&quot;1097&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;1116&quot; data-start=&quot;1102&quot; data-ke-size=&quot;size16&quot;&gt;백트래킹 동작 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-end=&quot;1399&quot; data-start=&quot;1118&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1203&quot; data-start=&quot;1118&quot;&gt;&lt;b&gt;재귀 호출 스택&lt;/b&gt;: DFS를 수행할 때 각 노드에 대한 호출은 스택에 쌓입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1203&quot; data-start=&quot;1170&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1203&quot; data-start=&quot;1170&quot;&gt;호출 순서: DFS(A) &amp;rarr; DFS(B) &amp;rarr; DFS(D)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1320&quot; data-start=&quot;1204&quot;&gt;&lt;b&gt;백트래킹&lt;/b&gt;: DFS(D)가 종료되면, 함수 호출 스택에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;D&lt;/b&gt;가 제거되면서 DFS(B)로 되돌아갑니다. 같은 방식으로 DFS(B)가 모든 인접 노드를 다 확인하면 다시 DFS(A)로 돌아갑니다.&lt;/li&gt;
&lt;li data-end=&quot;1399&quot; data-start=&quot;1321&quot;&gt;&lt;b&gt;즉, 재귀 함수가 종료될 때마다 스택에서 제거(팝)되어 바로 이전 호출(즉, 가장 최근의 부모 노드)로 제어가 넘어가는 것입니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>알고리즘</category>
      <category>dfs</category>
      <category>개념 정리</category>
      <category>백트래킹</category>
      <category>코딩테스트 합격자 되기 파이썬</category>
      <category>파이썬</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/100</guid>
      <comments>https://studycord.tistory.com/100#entry100comment</comments>
      <pubDate>Sun, 6 Apr 2025 23:48:41 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 가장 큰 수</title>
      <link>https://studycord.tistory.com/99</link>
      <description>&lt;h1&gt;파이썬 [프로그래머스] - 가장 큰 수&lt;/h1&gt;
&lt;h2&gt;문제 설명&lt;/h2&gt;
&lt;p&gt;프로그래머스의 &lt;strong&gt;가장 큰 수&lt;/strong&gt; 문제는 주어진 숫자 배열을 이어 붙여 만들 수 있는 가장 큰 수를 반환하는 문제입니다.&lt;br&gt;예를 들어, &lt;code&gt;[6, 10, 2]&lt;/code&gt;가 주어지면 숫자들을 적절히 이어 붙여 &lt;code&gt;6210&lt;/code&gt;을 만드는 것이 목표입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;문제 접근 방식&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;문자열 변환&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;주어진 숫자들을 문자열로 변환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;정렬 기준 설정&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;각 숫자 문자열을 반복하여 비교 기준을 만듭니다.&lt;br&gt;예를 들어, 숫자 &lt;code&gt;3&lt;/code&gt;은 &lt;code&gt;&amp;quot;333&amp;quot;&lt;/code&gt;으로, 숫자 &lt;code&gt;30&lt;/code&gt;은 &lt;code&gt;&amp;quot;303030&amp;quot;&lt;/code&gt;으로 변환하여 비교합니다.&lt;/li&gt;
&lt;li&gt;문자열은 첫 인덱스가 같으면 다음 인덱스로 넘어가서 대소비교를 하기 때문에 숫자 &amp;#39;30&amp;#39;이 뒤로 밀립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;내림차순 정렬&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;변환된 문자열들을 내림차순으로 정렬하여, 이어 붙였을 때 가장 큰 수가 나오도록 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결과 조합 및 반환&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;정렬된 문자열들을 이어 붙여 하나의 문자열로 만들고,&lt;br&gt;&lt;code&gt;int()&lt;/code&gt;를 이용해 불필요한 0을 제거한 후 최종 결과를 문자열로 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;문제 풀이&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(numbers):    
    # 1. 숫자들을 문자열로 변환
    s = list(map(str, numbers))

    # 2. 각 숫자 문자열을 3번 반복하여 비교 기준 생성, 내림차순 정렬
    a = sorted(s, key=lambda x: x * 3, reverse=True)

    # 3. 정렬된 문자열들을 이어 붙여 하나의 문자열로 만든 후, 
    #    int로 변환해 불필요한 0을 제거한 뒤 다시 문자열로 반환
    return str(int(&amp;quot;&amp;quot;.join(a)))&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;주의사항 및 팁&lt;/h2&gt;
&lt;p&gt;문자열 곱셈 활용:&lt;br&gt;x * 3은 숫자 문자열 x를 3번 반복하여 비교 기준을 만드는 기법으로,&lt;br&gt;서로 다른 자리수의 숫자들을 효과적으로 비교할 수 있습니다.&lt;br&gt;정렬 기준의 중요성:&lt;br&gt;올바른 정렬 기준을 설정해야 이어 붙였을 때 가장 큰 수를 만들 수 있습니다.&lt;br&gt;결과값 처리:&lt;br&gt;최종 결과 문자열을 int()로 변환하면, &amp;quot;0&amp;quot;으로 시작하는 불필요한 경우를 제거할 수 있습니다.&lt;/p&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>Python</category>
      <category>정렬</category>
      <category>코딩테스트 연습</category>
      <category>코딩테스트 정렬</category>
      <category>프로그래머스 가장 큰 수</category>
      <category>프로그래머스 가장 큰 수 파이썬</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/99</guid>
      <comments>https://studycord.tistory.com/99#entry99comment</comments>
      <pubDate>Thu, 20 Mar 2025 18:23:45 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 기능개발</title>
      <link>https://studycord.tistory.com/98</link>
      <description>&lt;h1&gt;파이썬 [프로그래머스] - 기능개발&lt;/h1&gt;
&lt;h2&gt;문제 설명&lt;/h2&gt;
&lt;p&gt;프로그래머스의 &lt;strong&gt;기능개발&lt;/strong&gt; 문제는 각 작업의 진행 상황(progresses)과 작업 속도(speeds)가 주어졌을 때,&lt;br&gt;작업이 100% 이상 완료되면 배포하는 방식으로, 배포마다 동시에 몇 개의 작업이 완료되는지를 구하는 문제입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;문제 조건&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 작업은 매일 일정한 속도로 진행됩니다.&lt;/li&gt;
&lt;li&gt;작업은 순서대로 배포되며, 앞 작업이 완료되어야 뒷 작업도 함께 배포될 수 있습니다.&lt;/li&gt;
&lt;li&gt;한 번의 배포에 여러 작업이 동시에 완료될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;문제 접근 방식&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;시간 시뮬레이션&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;&lt;code&gt;time&lt;/code&gt; 변수를 사용해 경과한 날짜를 추적합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;완료 조건 체크&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;각 작업의 진행도는 &lt;code&gt;progress + time * speed&lt;/code&gt;로 계산합니다.&lt;/li&gt;
&lt;li&gt;첫 번째 작업이 100% 이상이면 작업을 제거(pop)하고 배포할 작업의 수(&lt;code&gt;count&lt;/code&gt;)를 증가시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;배포 기록&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;첫 번째 작업이 아직 완료되지 않았다면, 지금까지 완료된 작업 수(&lt;code&gt;count&lt;/code&gt;)를 결과 리스트에 추가하고&lt;br&gt;하루(&lt;code&gt;time&lt;/code&gt;)를 증가시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최종 처리&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;모든 작업이 완료된 후, 마지막 배포된 작업 수를 결과에 추가합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;문제 풀이&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;내가 푼 코드&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(progresses, speeds):
  answer = []
  for i in range(len(progresses)):
      progresses[i] = 100 - progresses[i]
      if progresses[i] % speeds[i] != 0:
          progresses[i] = progresses[i] // speeds[i] + 1
      else:
          progresses[i] = progresses[i] // speeds[i]
  cnt = 1
  work_day = progresses[0]
  for i in range(1, len(progresses)):
      if progresses[i] &amp;lt;= work_day:
          cnt += 1
      else:
          answer.append(cnt)
          work_day = progresses[i]
          cnt = 1
  answer.append(cnt)
  return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GPT가 최적화 한 코드&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(progresses, speeds):
  answer = []
  time = 0
  count = 0

  # 모든 작업이 완료될 때까지 반복
  while len(progresses) &amp;gt; 0:
      # 첫 번째 작업이 완료되었는지 확인
      if (progresses[0] + time * speeds[0]) &amp;gt;= 100: 
          # 완료된 작업을 리스트에서 제거하고 배포할 작업 수 증가
          progresses.pop(0)
          speeds.pop(0)
          count += 1
      else:
          # 현재까지 완료된 작업이 있다면 배포 기록에 추가
          if count &amp;gt; 0:
              answer.append(count)
              count = 0
          # 하루를 증가시키며 작업 진행 상황 업데이트
          time += 1
  # 마지막에 남은 배포 작업 수 추가
  answer.append(count)
  return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>Python</category>
      <category>Time</category>
      <category>기능개발</category>
      <category>스택</category>
      <category>큐</category>
      <category>파이썬</category>
      <category>파이썬 기능개발</category>
      <category>프로그래머스</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/98</guid>
      <comments>https://studycord.tistory.com/98#entry98comment</comments>
      <pubDate>Wed, 12 Mar 2025 15:35:31 +0900</pubDate>
    </item>
    <item>
      <title>2025-03 목표</title>
      <link>https://studycord.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 지원할 회사 추려서 플래너에 작성하고, 제출일 2일 전까지 제출하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 3월 17일 전까지 프로그래머스 알고리즘 고득점 KIT 문제 다 풀고 블로그에 업로드하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 알고리즘 정리해서 올리기..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 딥러닝 이론, 실기 더 탄탄하게 다져서 깃허브에 올리기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 노션 이력서 작성하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 해커톤 회고록 작성하기.&lt;/p&gt;</description>
      <category>목표!!</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/97</guid>
      <comments>https://studycord.tistory.com/97#entry97comment</comments>
      <pubDate>Wed, 12 Mar 2025 15:00:46 +0900</pubDate>
    </item>
    <item>
      <title>[python] 프로그래머스 - 베스트 앨범</title>
      <link>https://studycord.tistory.com/96</link>
      <description>&lt;h1&gt;베스트 앨범 문제 풀이 및 상세 설명&lt;/h1&gt;
&lt;p&gt;프로그래머스의 &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42579&quot;&gt;베스트 앨범 문제&lt;/a&gt;는 각 장르별로 재생 횟수를 기준으로 노래들을 정렬하고, 장르의 총 재생 횟수가 높은 순으로 두 곡씩 선택하여 베스트 앨범을 구성하는 문제입니다.&lt;/p&gt;
&lt;h2&gt;문제 해결 접근 방식&lt;/h2&gt;
&lt;p&gt;문제를 해결하기 위한 주요 단계는 다음과 같습니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;장르별 분류:&lt;/strong&gt;&lt;br&gt;입력으로 주어진 &lt;code&gt;genres&lt;/code&gt;와 &lt;code&gt;plays&lt;/code&gt; 리스트를 이용하여, 각 장르에 해당하는 &lt;code&gt;(재생 횟수, 인덱스)&lt;/code&gt; 튜플들을 저장합니다.  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예를 들어, &lt;code&gt;&amp;quot;pop&amp;quot;&lt;/code&gt; 장르에 속하는 노래들의 재생 횟수와 해당 인덱스를 함께 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;내부 정렬:&lt;/strong&gt;&lt;br&gt;각 장르별 리스트를 재생 횟수가 높은 순으로 정렬합니다.  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;만약 재생 횟수가 같은 경우, 인덱스가 작은 순으로 정렬하여 우선순위를 결정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;장르 정렬:&lt;/strong&gt;&lt;br&gt;전체 장르를 해당 장르에 속하는 노래들의 총 재생 횟수를 기준으로 내림차순 정렬합니다.  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이를 통해 가장 인기 있는 장르부터 베스트 앨범에 반영할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;노래 선택:&lt;/strong&gt;&lt;br&gt;정렬된 각 장르별로 상위 2개의 노래(재생 횟수가 가장 높은 노래)를 선택하여 최종 결과 리스트에 추가합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;최종 결과 반환:&lt;/strong&gt;&lt;br&gt;선택된 노래들의 인덱스를 순서대로 반환하여 베스트 앨범을 구성합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이러한 단계들을 통해 문제를 구조적으로 해결할 수 있으며, 각 단계마다 정렬과 선택 기준을 명확히 하여 올바른 결과를 도출할 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;코드 구현&lt;/h2&gt;
&lt;p&gt;아래는 위의 문제 해결 접근 방식을 반영한 파이썬 코드입니다. 각 단계별로 중요한 부분에 주석을 추가하여 설명합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(genres, plays):
    # answer: 최종적으로 베스트 앨범에 들어갈 곡의 인덱스들을 저장할 리스트
    answer = []

    # hash_map: 각 장르를 key로 하여 (재생 횟수, 인덱스) 튜플 리스트를 value로 저장
    hash_map = {}

    # 1. 장르별로 (재생 횟수, 인덱스) 튜플을 hash_map에 저장
    for i in range(len(genres)):
        if genres[i] in hash_map:
            hash_map[genres[i]].append((plays[i], i))
        else:
            hash_map[genres[i]] = [(plays[i], i)]

    # 2. 각 장르 내에서 재생 횟수가 많은 순으로 정렬
    #    - 재생 횟수가 동일하면 인덱스가 작은 순으로 정렬하여 우선순위를 결정
    for genre in hash_map:
        hash_map[genre].sort(key=lambda x: (-x[0], x[1]))

    # 3. 전체 장르를 해당 장르의 총 재생 횟수를 기준으로 내림차순 정렬
    sorted_hash_map = dict(sorted(hash_map.items(), key=lambda x: -sum(play[0] for play in x[1])))

    # 4. 각 장르별로 상위 2개의 곡(재생 횟수 기준) 인덱스를 answer에 추가
    for genre in sorted_hash_map:
        # 장르별로 최대 2개의 곡을 선택
        answer.extend([index for _, index in hash_map[genre][:2]])

    return answer&lt;/code&gt;&lt;/pre&gt;</description>
      <category>문제 풀이/프로그래머스</category>
      <category>베스트 앨범</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <category>해시</category>
      <author>동까의 코딩</author>
      <guid isPermaLink="true">https://studycord.tistory.com/96</guid>
      <comments>https://studycord.tistory.com/96#entry96comment</comments>
      <pubDate>Wed, 12 Mar 2025 11:51:25 +0900</pubDate>
    </item>
  </channel>
</rss>