diff --git "a/week03/taewoo/Programmers_\355\203\200\352\262\237_\353\204\230\353\262\204.py" "b/week03/taewoo/Programmers_\355\203\200\352\262\237_\353\204\230\353\262\204.py" new file mode 100644 index 0000000..d32a832 --- /dev/null +++ "b/week03/taewoo/Programmers_\355\203\200\352\262\237_\353\204\230\353\262\204.py" @@ -0,0 +1,16 @@ +def solution(numbers, target): + answer = 0 + + def dfs(idx, total): + nonlocal answer + + if idx == len(numbers): + if total == target: + answer += 1 + return + + dfs(idx + 1, total + numbers[idx]) + dfs(idx + 1, total - numbers[idx]) + + dfs(0, 0) + return answer diff --git a/week03/taewoo/README.md b/week03/taewoo/README.md new file mode 100644 index 0000000..8aa33f4 --- /dev/null +++ b/week03/taewoo/README.md @@ -0,0 +1,177 @@ +# Week 1~4 개념 정리 + +코딩 테스트에서 자주 쓰는 1주차부터 4주차까지의 핵심 개념을 빠르게 복습할 수 있도록 정리했습니다. + +--- + +## 1주차: 시간복잡도 & 배열/문자열 + +### 시간복잡도(Big-O) +- **O(1)**: 입력 크기와 상관없이 연산 횟수가 거의 일정 +- **O(log N)**: 탐색 범위를 절반씩 줄이는 방식(이분 탐색) +- **O(N)**: 입력을 한 번 순회 +- **O(N log N)**: 정렬 기반 알고리즘에서 자주 등장 +- **O(N^2)**: 이중 반복문, 완전 비교 + +실전 팁: +- `N`이 큰데 이중 반복문이면 시간 초과 가능성이 큼 +- 파이썬에서는 `list in` 탐색보다 `set`, `dict` 조회를 우선 고려 + +### 배열(Array) +- 인덱스로 빠르게 접근 가능 +- 삽입/삭제 위치에 따라 비용 차이 큼 +- 투 포인터, 슬라이딩 윈도우 패턴이 자주 사용됨 + +### 문자열(String) +- 불변(immutable) 자료형이라 반복 연결(`+`)은 비효율적일 수 있음 +- 누적 조합은 `list`에 담고 `''.join()`을 활용 +- 문자 빈도는 `dict`, `collections.Counter` 사용 + +### 1주차 기초 문제 +- 프로그래머스: `같은 숫자는 싫어` +- 프로그래머스: `K번째수` +- 백준: `10818 최소, 최대` +- 백준: `1152 단어의 개수` +- 백준: `2908 상수` + +--- + +## 2주차: 스택, 큐, 해시맵 + +### 스택(Stack, LIFO) +- 나중에 넣은 값을 먼저 꺼냄 +- 괄호 짝 맞추기, 되돌리기(undo), 단조 스택 문제에 활용 +- 파이썬: `append`, `pop` + +### 큐(Queue, FIFO) +- 먼저 넣은 값을 먼저 꺼냄 +- BFS, 작업 스케줄링, 순차 처리에 활용 +- 파이썬: `collections.deque`의 `append`, `popleft` + +### 해시맵(HashMap, dict) +- 평균적으로 빠른 삽입/조회/삭제 +- 빈도수 계산, 중복 체크, 인덱스 저장 문제에 강함 +- 키 존재 여부 확인: `if key in dict` + +### 2주차 기초 문제 +- 프로그래머스: `올바른 괄호` +- 프로그래머스: `기능개발` +- 프로그래머스: `완주하지 못한 선수` +- 백준: `10828 스택` +- 백준: `10845 큐` + +--- + +## 3주차: 재귀 & 완전 탐색 + +### 재귀(Recursion) +- 함수가 자기 자신을 호출해 문제를 작은 단위로 분해 +- **종료 조건(base case)**이 반드시 필요 +- 깊이가 매우 깊어지면 재귀 한도 이슈를 고려해야 함 + +### 완전 탐색(Brute Force) +- 가능한 모든 경우를 시도 +- 정답 보장 장점이 있지만 경우의 수가 크면 비효율적 +- 순열/조합/부분집합을 재귀(백트래킹)로 구현하는 경우가 많음 + +### 백트래킹(Backtracking) +- 조건에 맞지 않으면 더 깊게 가지 않고 되돌아감(가지치기) +- 완전 탐색의 탐색 공간을 줄이는 핵심 전략 + +### 3주차 기초 문제 +- 프로그래머스: `모의고사` +- 프로그래머스: `소수 찾기` +- 백준: `2798 블랙잭` +- 백준: `2309 일곱 난쟁이` +- 백준: `9663 N-Queen` (입문 이후 도전) + +--- + +## 4주차: DFS & BFS + +### DFS(깊이 우선 탐색) +- 한 경로를 끝까지 탐색한 뒤 되돌아옴 +- 구현: 재귀 또는 스택 +- 경로 탐색, 연결 요소 개수, 조합형 탐색에 적합 + +### BFS(너비 우선 탐색) +- 가까운 노드부터 레벨 순으로 탐색 +- 구현: 큐(`deque`) +- **최단 거리(간선 가중치가 동일할 때)** 문제에 강함 + +### 그래프/격자 탐색 핵심 +- 방문 체크(`visited`)를 정확히 관리 +- 이동 방향 벡터(`dx`, `dy`) 패턴을 습관화 +- 범위 검사(인덱스 유효성) 누락 방지 + +### 4주차 기초 문제 +- 프로그래머스: `타겟 넘버` +- 프로그래머스: `게임 맵 최단거리` +- 백준: `1260 DFS와 BFS` +- 백준: `2606 바이러스` +- 백준: `2178 미로 탐색` + +--- + +## 문제 풀이 공통 루틴 + +1. 입력 크기로 시간복잡도 상한 먼저 판단 +2. 자료구조 선택(배열/해시/스택/큐) +3. 탐색 방식 선택(완탐/DFS/BFS) +4. 예외 케이스(빈 입력, 경계값) 점검 +5. 작은 예제로 손코딩 검증 후 구현 + +이 루틴을 반복하면 문제 유형이 달라도 풀이 속도와 정확도를 안정적으로 올릴 수 있습니다. + +--- + +## 파이썬 기초 (코테용) + +### 1) 자주 쓰는 자료형 +- `list`: 순서 있음, 수정 가능 + - 예: `arr = [1, 2, 3]`, `arr.append(4)`, `arr.pop()` +- `tuple`: 순서 있음, 수정 불가 + - 예: `point = (x, y)` +- `dict`: 키-값 저장, 조회 빠름 + - 예: `d = {"a": 1}`, `d["b"] = 2` +- `set`: 중복 제거, 포함 여부 확인 빠름 + - 예: `s = {1, 2, 2}` -> `{1, 2}` + +### 2) 반복문/조건문 +```python +for x in [1, 2, 3]: + if x % 2 == 0: + print("짝수") + else: + print("홀수") +``` +- 범위 반복: `for i in range(n):` +- 역순 반복: `for i in range(n - 1, -1, -1):` + +### 3) 함수 +```python +def add(a, b): + return a + b +``` +- 코테에서는 작은 기능 단위로 함수 분리하면 디버깅이 쉬움 +- 재귀 함수는 종료 조건(base case)을 반드시 작성 + +### 4) 코테 필수 문법 +- 정렬: `arr.sort()`, `sorted(arr, key=...)` +- 최댓값/최솟값: `max(arr)`, `min(arr)` +- 합계: `sum(arr)` +- 문자열 합치기: `"".join(list_of_str)` +- 개수 세기: `dict` 또는 `collections.Counter` + +### 5) 자주 쓰는 라이브러리 +- 큐: `from collections import deque` + - `q.append(x)`, `q.popleft()` +- 우선순위 큐(최소 힙): `import heapq` + - `heapq.heappush(h, x)`, `heapq.heappop(h)` + +### 6) 자주 하는 실수 +- 리스트 복사 시 `b = a`는 같은 객체 참조 + - 복사는 `b = a[:]` 또는 `b = list(a)` +- 2차원 배열 생성 시 `[[0] * m] * n`은 같은 행 참조 + - `[[0] * m for _ in range(n)]` 사용 +- `in list` 탐색이 많으면 `set` 변환을 고려