Programmers Level 4에서 요구하는 Python 고급 도구와 알고리즘 패턴을 Data Scientist와 AI Engineer 트랙별 우선순위로 정리한다. Dijkstra, DP 최적화, 유니온 파인드, SQL 윈도우 함수가 핵심이다.
Code Test
저자
Kwangmin Kim
공개
2026년 04월 04일
1 개요
Level 4는 DS 트랙과 AIE 트랙이 명확히 갈린다. DS 트랙은 SQL 고급 분석(Window Functions, CTE)과 투 포인터 패턴을 중심으로 준비한다. AIE 트랙은 그래프 알고리즘(Dijkstra, Floyd-Warshall), Union-Find, 비트 마스킹 등 시스템 수준의 알고리즘 구현 능력을 요구한다.
2 DS vs AIE 트랙 우선순위
도구/개념
DS 우선순위
AIE 우선순위
설명
Dijkstra (heapq 기반)
★☆☆
★★★
가중치 그래프 최단 경로
Floyd-Warshall
★☆☆
★★★
전체 쌍 최단 경로
Union-Find
★☆☆
★★★
연결 성분, MST
배낭 문제 DP
★★☆
★★★
선택 최적화
투 포인터 / 슬라이딩 윈도우
★★★
★★★
구간 탐색 최적화
SQL Window Functions
★★★
★★☆
분석 쿼리
SQL CTE (WITH)
★★★
★★☆
복잡 쿼리 분해
비트 마스킹
★☆☆
★★★
부분집합, 상태 압축 DP
모노톤 스택
★★☆
★★★
다음 큰 원소, 히스토그램
3 Dijkstra — 가중치 그래프 최단 경로 (AIE 핵심)
import heapqdef dijkstra(graph, start, n):""" graph: {node: [(neighbor, weight), ...]} n: 전체 노드 수 """ INF =float('inf') dist = [INF] * (n +1) dist[start] =0 pq = [(0, start)] # (거리, 노드)while pq: d, u = heapq.heappop(pq) # 현재까지의 최단 거리 노드if d > dist[u]: # 이미 처리된 노드이면 skipcontinuefor v, w in graph[u]:if dist[u] + w < dist[v]: dist[v] = dist[u] + w # 거리 갱신 heapq.heappush(pq, (dist[v], v))return dist# 예시graph = {1: [(2, 2), (3, 5)],2: [(3, 1), (4, 7)],3: [(4, 3)],4: []}dist = dijkstra(graph, 1, 4)# dist → [inf, 0, 2, 3, 6]# dist[1]=0(시작), dist[2]=2, dist[3]=3(1→2→3), dist[4]=6(1→2→3→4)
4 Floyd-Warshall — 전체 쌍 최단 경로 (AIE 핵심)
def floyd_warshall(n, edges): INF =float('inf') dist = [[INF] * (n+1) for _ inrange(n+1)]for i inrange(n+1): dist[i][i] =0for u, v, w in edges: dist[u][v] = w # 방향 그래프# 경유 노드 k를 순서대로 고려for k inrange(1, n+1):for i inrange(1, n+1):for j inrange(1, n+1):if dist[i][k] + dist[k][j] < dist[i][j]: dist[i][j] = dist[i][k] + dist[k][j]return dist# 시간 복잡도: O(V^3) — 노드 수 적을 때 (V <= 500 정도) 사용
# 오른쪽 첫 번째 더 큰 값 찾기 — Next Greater Elementdef next_greater(arr): n =len(arr) result = [-1] * n stack = [] # 인덱스 저장for i inrange(n):while stack and arr[stack[-1]] < arr[i]: j = stack.pop() result[j] = arr[i] # j번째 원소의 다음 큰 값 = arr[i] stack.append(i)return resultnext_greater([2, 1, 5, 3, 4])# → [5, 5, -1, 4, -1]# 2의 다음 큰 값=5, 1의 다음 큰 값=5, 5는 없음(-1), 3의 다음 큰 값=4, 4는 없음(-1)
10 SQL Window Functions (DS 핵심)
-- ROW_NUMBER: 각 행에 고유 번호 부여SELECT name, salary, department,ROW_NUMBER() OVER (PARTITIONBY department ORDERBY salary DESC) AS rank_in_deptFROM employees;-- 부서별로 급여 내림차순 순위를 매긴다. 동점도 다른 번호를 받는다.-- RANK vs DENSE_RANKSELECT name, score,RANK() OVER (ORDERBY score DESC) ASrank, -- 동점이면 같은 순위, 다음 순위 건너뜀DENSE_RANK() OVER (ORDERBY score DESC) ASdense_rank-- 동점이면 같은 순위, 다음 순위 이어감FROM scores;-- score: 100, 100, 90-- RANK: 1, 1, 3-- DENSE_RANK: 1, 1, 2-- LAG / LEAD: 이전/다음 행 값 참조SELECTdate, revenue,LAG(revenue) OVER (ORDERBYdate) AS prev_revenue, revenue -LAG(revenue) OVER (ORDERBYdate) ASchangeFROM sales;-- 전날 대비 매출 변화를 계산한다-- 이동 평균 (3일)SELECTdate, revenue,AVG(revenue) OVER (ORDERBYdateROWSBETWEEN2PRECEDINGANDCURRENTROW) AS ma3FROM sales;-- 누적 합SELECTdate, revenue,SUM(revenue) OVER (ORDERBYdateROWSUNBOUNDEDPRECEDING) AS cumsumFROM sales;
11 SQL CTE (WITH) (DS 핵심)
-- CTE로 복잡한 쿼리 분해WITHdept_avg AS (SELECT department, AVG(salary) AS avg_salaryFROM employeesGROUPBY department),above_avg AS (SELECT e.name, e.salary, e.department, d.avg_salaryFROM employees eJOIN dept_avg d ON e.department = d.departmentWHERE e.salary > d.avg_salary)SELECT*FROM above_avgORDERBY department, salary DESC;-- 부서 평균보다 급여가 높은 직원을 조회한다-- 다중 CTEWITHmonthly_sales AS (SELECT DATE_FORMAT(date, '%Y-%m') ASmonth, SUM(amount) AS totalFROM ordersGROUPBYmonth),ranked AS (SELECT*, RANK() OVER (ORDERBY total DESC) AS rnkFROM monthly_sales)SELECTmonth, totalFROM rankedWHERE rnk <=3; -- 매출 Top 3 월 조회