์๊ณ ๋ฆฌ์ฆ์ ์ฃผ์ด์ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋จ๊ณ์ ์ธ ์ ์ฐจ์ด๋ค. ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ์ ํํ๋ฉด ์๊ฐ๊ณผ ๊ณต๊ฐ์ ์ ์ฝํ ์ ์๊ณ , ๋ฌธ์ ๋ฅผ ๋ ๋น ๋ฅด๊ฒ ํด๊ฒฐํ ์ ์๊ธฐ์ ์์๋ฌ์ผ๊ฒ ์ง? (๋งจ๋ ๊น๋จน๋๋ค)
Brute Force
๋ธ๋ฃจํธํฌ์ค ์๊ณ ๋ฆฌ์ฆ์ ๋ชจ๋ ๊ฐ๋ฅํ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ค ๊ณ ๋ คํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋งค์ฐ ์ง๊ด์ ์ด๊ณ ๊ตฌํํ๊ธฐ ์ฝ์ง๋ง, ๊ฒฝ์ฐ์ ์๊ฐ ๋ง์ ๊ฒฝ์ฐ ์๊ฐ ๋ณต์ก๋๊ฐ ๋งค์ฐ ์ปค์ง ์ ์๋ค. ๋ฐ๋ผ์ ์ฃผ๋ก ์ ํ์ด ์ ๊ฑฐ๋, ๋ฌธ์ ์ ํฌ๊ธฐ๊ฐ ์์ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค.
ํน์ง
- ๋จ์ํ๊ณ ์ง๊ด์ : ์๊ณ ๋ฆฌ์ฆ์ด ๋งค์ฐ ๊ฐ๋จํ๊ณ ์ดํดํ๊ธฐ ์ฌ์.
- ์๊ฐ ๋ณต์ก๋: ๋ฌธ์ ์ ํฌ๊ธฐ์ ๋ฐ๋ผ O(n^2), O(n!)์ ๊ฐ์ ๋์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง ์ ์์.
- ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ์๋: ์ต์ ํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ง ์๊ณ , ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ๋ฅผ ์๋ํ๋ ๋ฐฉ์์ด๋ค.
์ฌ์ฉ ์ฌ๋ก
- ๊ฐ๋ฅํ ์กฐํฉ, ์์ด์ ๋ชจ๋ ํ์ํ๋ ๋ฌธ์ .
- ์ ํ์ด ์์ ๋ฌธ์ ์์ ์ต์ ์ ํด๋ต์ ๊ตฌํ ๋.
- ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์์ด ๊ฐ๋จํ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํ ๊ฒฝ์ฐ.
์ฃผ์ด์ง ๋ฐฐ์ด์์ ๋ ์์ ํฉ์ด ํน์ ๊ฐ์ด ๋๋์ง ํ์ธํ๋ ๋ฌธ์ ๋ฅผ ๋ธ๋ฃจํธํฌ์ค๋ก ํด๊ฒฐํ ์ ์๋ค. ์ด ๊ฒฝ์ฐ ๋ฐฐ์ด์ ๋ชจ๋ ์์๋ฅผ ๋ ๊ฐ์ฉ ๋น๊ตํ๋ฉด ๋๋ค.
def brute_force_two_sum(nums, target):
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return (nums[i], nums[j])
return None
nums = [2, 7, 11, 15]
target = 9
print(brute_force_two_sum(nums, target)) # (2, 7)
์ด์ง ํ์ (Binary Search)
์ด์ง ํ์์ ์ ๋ ฌ๋ ๋ฐฐ์ด์์ ํน์ ๊ฐ์ ์ฐพ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋ฐฐ์ด์ ๋ฐ์ผ๋ก ๋๋์ด ๊ฒ์ ๋ฒ์๋ฅผ ์ขํ ๋๊ฐ๋ฉฐ, O(log n)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ค. ๋ฐ๋ผ์ ์ ๋ ฌ๋ ๋ฐฐ์ด์์ ์ํ๋ ๊ฐ์ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ ์๋ค.
ํน์ง
- ์๊ฐ ๋ณต์ก๋: O(log n)
- ๋ฐฐ์ด์ด ๋ฐ๋์ ์ ๋ ฌ๋์ด ์์ด์ผ ํ๋ค.
- ์ค์๊ฐ์ ๊ธฐ์ค์ผ๋ก ๊ฒ์ ๋ฒ์๋ฅผ ์ ๋ฐ์ฉ ๋๋๋ฉด์ ํ์ํ๋ค.
- ๋ฐ๋ณต๋ฌธ ๋๋ ์ฌ๊ท์ ์ผ๋ก ๊ตฌํํ ์ ์๋ค.
์ฌ์ฉ ์ฌ๋ก
- ์ ๋ ฌ๋ ๋ฐฐ์ด์์ ๊ฐ์ ์ฐพ๋ ๋ฌธ์ .
- ๊ตฌ๊ฐ ํ์ ๋ฌธ์ .
- ์ด์ง ํ์ ํธ๋ฆฌ์์ ์ฌ์ฉ๋๋ ํ์ ๋ฐฉ์.
๋ค์์ ์ด์ง ํ์์ ์ฌ์ฉํ์ฌ ์ ๋ ฌ๋ ๋ฐฐ์ด์์ ํน์ ๊ฐ์ ์ฐพ๋ ์ฝ๋์ด๋ค.
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1 # ๊ฐ์ด ์์ผ๋ฉด -1 ๋ฐํ
arr = [1, 3, 5, 7, 9]
target = 5
print(binary_search(arr, target)) # 2 (5๋ ์ธ๋ฑ์ค 2์ ์์)
๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ (Greedy Algorithm)
๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋งค ๋จ๊ณ์์ ์ต์ ์ ์ ํ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฒด ๋ฌธ์ ์ ๋ํ ์ต์ ํด๋ฅผ ๊ตฌํ๋ ๊ฒ์ด ์๋๋ผ, ์ง์ญ์ ์ผ๋ก ์ต์ ์ธ ์ ํ์ ๋ฐ๋ณตํ๋ฉฐ ํด๊ฒฐํ๋ค. ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ํญ์ ์ต์ ํด๋ฅผ ๋ณด์ฅํ์ง ์์ง๋ง, ๋ง์ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ ์ ์๋ค.
ํน์ง
- ๋จ๊ณ๋ณ๋ก ์ต์ ์ ์ ํ์ ํ๋ค.
- ์ ์ญ ์ต์ ํด๋ฅผ ๊ตฌํ์ง ์์ง๋ง, ์ง์ญ ์ต์ ์ ํ์ด ์ ์ฒด ์ต์ ์ ์ด๋ฃฌ๋ค๊ณ ๊ฐ์ ํ๋ค.
- ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก, ๊ตฌํ์ด ๋น๊ต์ ์ฝ๋ค.
- ๊ทธ๋ฌ๋ ๋ชจ๋ ๋ฌธ์ ์ ์ ํฉํ์ง ์๋ค. ์ผ๋ถ ๋ฌธ์ ์์๋ ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์ต์ ์ ํด๋ฅผ ๋ณด์ฅํ์ง ์์ ์ ์๋ค.
์ฌ์ฉ ์ฌ๋ก
- ์ต์ ์ ์ฅ ํธ๋ฆฌ (Prim, Kruskal ์๊ณ ๋ฆฌ์ฆ)
- ํ๋ ์ ํ ๋ฌธ์
- ๋์ ๊ตํ ๋ฌธ์
์ฃผ์ด์ง ๋์ ๋ค๋ก ํน์ ๊ธ์ก์ ๋ง๋ค๊ธฐ ์ํ ์ต์ ๋์ ๊ฐ์๋ฅผ ๊ตฌํ๋ ๋ฌธ์ ์ด๋ค. ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํ์ฌ ๊ฐ์ฅ ํฐ ๋์ ๋ถํฐ ์ฌ์ฉํ์ฌ ์ต์ ๋์ ๊ฐ์๋ฅผ ๊ตฌํ ์ ์๋ค.
def greedy_coin_change(coins, target):
coins.sort(reverse=True) # ํฐ ๋์ ๋ถํฐ ์ฌ์ฉ
result = 0
for coin in coins:
result += target // coin
target %= coin
return result
coins = [1, 5, 10, 25]
target = 30
print(greedy_coin_change(coins, target)) # 2 (1 x 25, 1 x 5)
๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ (Dynamic Programming)
๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ(DP)์ ๋ฌธ์ ๋ฅผ ๋ ์์ ๋ถ๋ถ ๋ฌธ์ ๋ก ๋๋์ด ํด๊ฒฐํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ์ฌ ์ค๋ณต ๊ณ์ฐ์ ํผํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ด ๋ฐฉ๋ฒ์ ์ต์ ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ ์ฉํ๋ฉฐ, ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ฌ๋ฌ ๋ฒ ๊ณ์ฐํ์ง ์๋๋ก ํ์ฌ ์๊ฐ ๋ณต์ก๋๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์๋ค.
ํน์ง
- ๋ถ๋ถ ๋ฌธ์ ์ ํด๊ฒฐ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ์ฌ ์ค๋ณต ๊ณ์ฐ์ ๋ฐฉ์งํ๋ค.
- ํ์ ๋ฌธ์ ํด๊ฒฐ์ ๊ฒฐ๊ณผ๋ฅผ ์์ ๋ฌธ์ ํด๊ฒฐ์ ์ฌ์ฌ์ฉํ๋ค.
- ์ฌ๊ท์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋, ์ด์ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์ (Memoization) ๋ฐฉ์์ผ๋ก ์ ์ฅํ์ฌ ๊ณ์ฐ ํจ์จ์ฑ์ ๋์ธ๋ค.
- ๋ณดํต ํ์ ๊ณต๊ฐ์ ์ค์ด๋ ๋ฐฉ์์ผ๋ก ์๋ํ๋ค.
์ฌ์ฉ ์ฌ๋ก
- ํผ๋ณด๋์น ์์ด
- ์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ (๋ค์ต์คํธ๋ผ, ํ๋ก์ด๋-์์ )
- ๋ฐฐ๋ญ ๋ฌธ์ (Knapsack problem)
- ๋ฌธ์์ด ํธ์ง ๊ฑฐ๋ฆฌ (Levenshtein Distance)
ํผ๋ณด๋์น ์์ด์ ๊ณ์ฐํ๋ ๋ฌธ์ ์์ ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ์ ํ์ฉํ ์ ์๋ค. ์ค๋ณต ๊ณ์ฐ์ ํผํ๊ณ , ์ด์ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ์ฌ ํจ์จ์ ์ผ๋ก ๊ตฌํ ์ ์๋ค.
# ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ์ ํ์ฉํ ํผ๋ณด๋์น ์์ด ๊ณ์ฐ
def fib(n):
dp = [0] * (n + 1)
dp[1] = 1
for i in range(2, n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
print(fib(10)) # 55
BFS (Breadth-First Search)
BFS(๋๋น ์ฐ์ ํ์)๋ ๊ทธ๋ํ๋ ํธ๋ฆฌ์์ ๋์ด ์ฐ์ ์ผ๋ก ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. BFS๋ ์์ ๋ ธ๋์์ ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ์ฐจ๋ก๋ก ํ์ํ๋ฉฐ, ํ๋ฅผ ์ด์ฉํด ๊ตฌํ๋๋ค.
ํน์ง
- ์์ ๋ ธ๋์์ ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ํ์ํ๋ค.
- ํ(Queue)๋ฅผ ์ฌ์ฉํ์ฌ, ๊ฐ ๋ ธ๋๋ฅผ ํ์ํ ํ ๊ทธ์ ์ฐ๊ฒฐ๋ ๋ ธ๋๋ฅผ ์ฐจ๋ก๋ก ํ์ ๋ฃ์ด ํ์ํ๋ค.
- ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฐ ์ ์ฉํ๋ค.
์ฌ์ฉ ์ฌ๋ก
- ์ต๋จ ๊ฒฝ๋ก ์ฐพ๊ธฐ: ํน์ ๋ ธ๋์์ ๋ค๋ฅธ ๋ ธ๋๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- ๋๋น ์ฐ์ ํ์์ด ํ์ํ ๋ฌธ์ ์์ ์ฌ์ฉ๋๋ค.
- ๊ทธ๋ํ์ ์ฐ๊ฒฐ ์์๋ฅผ ์ฐพ๋ ๋ฐ ์ ์ฉํ๋ค.
๋ค์์ BFS๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋ํ์์ ํน์ ๋ ธ๋๋ฅผ ํ์ํ๋ ์ฝ๋์ด๋ค.
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
while queue:
node = queue.popleft()
if node not in visited:
print(node, end=" ") # ๋ฐฉ๋ฌธํ ๋
ธ๋ ์ถ๋ ฅ
visited.add(node)
queue.extend(graph[node] - visited) # ์ฐ๊ฒฐ๋ ๋
ธ๋๋ฅผ ํ์ ์ถ๊ฐ
# ๊ทธ๋ํ ํํ (์ธ์ ๋ฆฌ์คํธ)
graph = {
1: {2, 3},
2: {1, 4},
3: {1, 5},
4: {2},
5: {3}
}
bfs(graph, 1) # 1 2 3 4 5
DFS (Depth-First Search)
DFS(๊น์ด ์ฐ์ ํ์)์ ๊ทธ๋ํ๋ ํธ๋ฆฌ์์ ๊น์ด ์ฐ์ ์ผ๋ก ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. DFS๋ ์คํ(ํน์ ์ฌ๊ท ํธ์ถ)์ ์ด์ฉํด ๊ตฌํ๋๋ค. DFS๋ ๊ฐ๋ฅํ ํ ๊น๊ฒ ํ์ํ๊ณ , ๋ ์ด์ ๊น๊ฒ ๊ฐ ์ ์์ผ๋ฉด ๋ค์ ๋์์ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ํ์ํ๋ค.
ํน์ง
- ์์ ๋ ธ๋์์ ๊ฐ๋ฅํ ํ ๊น๊ฒ ํ์ํ๋ค.
- ์คํ(Stack)์ ์ฌ์ฉํ์ฌ ํ์ํ๋ฉฐ, ์ฌ๊ท๋ฅผ ์ด์ฉํ ๊ตฌํ๋ ๊ฐ๋ฅํ๋ค.
- ๊ฒฝ๋ก๊ฐ ๊น๊ณ ๋ณต์กํ ๊ทธ๋ํ์์ ์ ์ฉํ๋ค.
์ฌ์ฉ ์ฌ๋ก
- ๊ทธ๋ํ ํ์ ๋ฐ ํธ๋ฆฌ ํ์์์ ์ฌ์ฉ๋๋ค.
- ๊ฒฝ๋ก ์ฐพ๊ธฐ ๋ฐ ๋ฐฑํธ๋ํน ๋ฌธ์ ์์ ์ ์ฉํ๋ค.
- ๋ชจ๋ ๊ฒฝ๋ก ํ์์ด ํ์ํ ๋ ์ฌ์ฉ๋๋ค.
๋ค์์ DFS๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋ํ์์ ๋ชจ๋ ๋ ธ๋๋ฅผ ํ์ํ๋ ์ฝ๋์ด๋ค.
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=" ") # ๋ฐฉ๋ฌธํ ๋
ธ๋ ์ถ๋ ฅ
for neighbor in graph[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
# ๊ทธ๋ํ ํํ (์ธ์ ๋ฆฌ์คํธ)
graph = {
1: {2, 3},
2: {1, 4},
3: {1, 5},
4: {2},
5: {3}
}
dfs(graph, 1) # 1 2 4 3 5
์ต์ ํ (Min Heap)
์ต์ ํ(Min Heap)์ ์ฐ์ ์์ ํ๋ฅผ ๊ตฌํํ๋ ์๋ฃ ๊ตฌ์กฐ๋ก, ๋ถ๋ชจ ๋ ธ๋๊ฐ ์์ ๋ ธ๋๋ณด๋ค ์์ ๊ฐ์ ๊ฐ๋ ์์ ์ด์ง ํธ๋ฆฌ ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค. ์ต์ ํ์ ๋ฃจํธ ๋ ธ๋๊ฐ ํญ์ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ง๋ฉฐ, ์ด ๊ฐ์ ๋น ๋ฅด๊ฒ ๊บผ๋ผ ์ ์๋ค. ์ด ๊ตฌ์กฐ๋ ์ฝ์ ๊ณผ ์ญ์ ๊ฐ ํจ์จ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฉฐ, ์ฐ์ ์์ ํ์์ ์์ฃผ ์ฌ์ฉ๋๋ค.
ํน์ง
- ๋ถ๋ชจ ๋ ธ๋๊ฐ ํญ์ ์์ ๋ ธ๋๋ณด๋ค ์์ ๊ฐ์ ๊ฐ์ง๋ค.
- ๋ฃจํธ ๋ ธ๋๋ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ง๋ค.
- ์์ ์ด์ง ํธ๋ฆฌ ํํ๋ก ๊ตฌํ๋๋ค.
- ์ฝ์ ๊ณผ ์ญ์ ๊ฐ O(log n)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ๋๋ค.
์ฌ์ฉ ์ฌ๋ก
- ์ฐ์ ์์ ํ๋ฅผ ๊ตฌํํ ๋ ์ฌ์ฉ๋๋ค.
- ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๊ฐ์ ์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ์์ ์ฐ์ ์์ ํ๊ฐ ํ์ํ ๋ ์ฌ์ฉ๋๋ค.
- ํ ์ ๋ ฌ์์ ์ฌ์ฉ๋๋ค.
ํ์ด์ฌ์์๋ heapq
๋ชจ๋์ ์ฌ์ฉํ์ฌ ์ต์ ํ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค. heapq
๋ ์ต์ ํ์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ฉฐ, ํ์ ๊ฐ์ฅ ์์ ๊ฐ์ ๋น ๋ฅด๊ฒ ์ถ์ถํ ์ ์๋ค.
import heapq
# ์ต์ ํ์ ์ด์ฉํ ์์
heap = []
# ์ต์ ํ์ ๊ฐ ์ฝ์
heapq.heappush(heap, 3) # O(log n)
heapq.heappush(heap, 1)
heapq.heappush(heap, 2)
# ์ต์ ํ์์ ๊ฐ์ฅ ์์ ๊ฐ ์ถ์ถ
print(heapq.heappop(heap)) # 1 (์ต์๊ฐ)
print(heapq.heappop(heap)) # 2
print(heapq.heappop(heap)) # 3
'๐ป Programming > ์ฝ๋ฉ ํ ์คํธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฝ๋ฉ ํ ์คํธ๋ฅผ ์ํ '์๋ฃ ๊ตฌ์กฐ' (0) | 2025.01.15 |
---|---|
[ํ๋ก๊ทธ๋๋จธ์ค] 'ํ์ด์ฌ์ ํ์ด์ฌ๋ต๊ฒ' ๊ฐ์ ์ ๋ฆฌ (0) | 2021.08.03 |