diff --git a/apps/docs/content/backtracking/39-combination-sum.mdx b/apps/docs/content/backtracking/39-combination-sum.mdx
new file mode 100644
index 0000000..adf8d52
--- /dev/null
+++ b/apps/docs/content/backtracking/39-combination-sum.mdx
@@ -0,0 +1,53 @@
+---
+title: '39. Combination Sum'
+description: Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order
+sidebar:
+ label: 'Combination Sum'
+ badge: 'Medium'
+---
+
+Array
+
+### Example 1:
+- Input: `candidates = [2,3,6,7], target = 7`
+- Output: `[[2,2,3],[7]]`
+- Explanation: `2` and `3` are `candidates`, and `2 + 2 + 3 = 7`. Note that `2` can be used multiple times. `7` is a candidate, and `7 = 7`. These are the only two combinations.
+
+### Example 2:
+- Input: `candidates = [2,3,5], target = 8`
+- Output: `[[2,2,2,2],[2,3,3],[3,5]]`
+
+### Example 3:
+- Input: `candidates = [2], target = 1`
+- Output: `[]`
+
+### Constraints:
+
+- `1 <= candidates.length <= 30`
+- `2 <= candidates[i] <= 40`
+- All elements of `candidates` are distinct.
+- `1 <= target <= 40`
+
+## Solution
+
+```py
+class Solution:
+ def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
+ candidates.sort()
+ result, path = [], []
+
+ def backtrack(start, remaining):
+ if remaining == 0:
+ result.append(path[:])
+ return
+ for i in range(start, len(candidates)):
+ if candidates[i] > remaining:
+ break
+
+ path.append(candidates[i])
+ backtrack(i, remaining - candidates[i])
+ path.pop()
+
+ backtrack(0, target)
+ return result
+```
diff --git a/apps/docs/content/backtracking/46-permutations.mdx b/apps/docs/content/backtracking/46-permutations.mdx
new file mode 100644
index 0000000..ad23c6e
--- /dev/null
+++ b/apps/docs/content/backtracking/46-permutations.mdx
@@ -0,0 +1,52 @@
+---
+title: '46. Permutations'
+description: Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order
+sidebar:
+ label: 'Permutations'
+ badge: 'Medium'
+---
+
+Array
+
+### Example 1:
+- Input: `nums = [1,2,3]`
+- Output: `[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]`
+
+### Example 2:
+- Input: `nums = [0,1]`
+- Output: `[[0,1],[1,0]]`
+
+### Example 3:
+- Input: `nums = [1]`
+- Output: `[[1]]`
+
+### Constraints:
+
+- `1 <= nums.length <= 6`
+- `-10 <= nums[i] <= 10`
+- All the integers of `nums` are unique.
+
+## Solution
+
+```py
+class Solution:
+ def permute(self, nums: list[int]) -> list[list[int]]:
+ result, path = [], []
+ used = [False] * len(nums)
+
+ def backtrack():
+ if len(path) == len(nums):
+ result.append(path[:])
+ return
+ for i in range(len(nums)):
+ if used[i]:
+ continue
+ used[i] = True
+ path.append(nums[i])
+ backtrack()
+ path.pop()
+ used[i] = False
+
+ backtrack()
+ return result
+```
diff --git a/apps/docs/content/backtracking/78-subsets.mdx b/apps/docs/content/backtracking/78-subsets.mdx
new file mode 100644
index 0000000..606460b
--- /dev/null
+++ b/apps/docs/content/backtracking/78-subsets.mdx
@@ -0,0 +1,41 @@
+---
+title: '78. Subsets'
+description: Given an integer array nums of unique elements, return all possible subsets (the power set)
+sidebar:
+ label: 'Subsets'
+ badge: 'Medium'
+---
+
+Array
+
+### Example 1:
+- Input: `nums = [1,2,3]`
+- Output: `[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]`
+
+### Example 2:
+- Input: `nums = [0]`
+- Output: `[[],[0]]`
+
+### Constraints:
+
+- `1 <= nums.length <= 10`
+- `-10 <= nums[i] <= 10`
+- All the numbers of `nums` are unique.
+
+## Solution
+
+```py
+class Solution:
+ def subsets(self, nums: list[int]) -> list[list[int]]:
+ res = []
+
+ def backtrack(i, path):
+ res.append(path[:])
+ for num_idx in range(i, len(nums)):
+ path.append(nums[num_idx])
+ backtrack(num_idx + 1, path)
+ path.pop()
+
+ backtrack(0, [])
+ return res
+```
diff --git a/apps/docs/content/backtracking/index.mdx b/apps/docs/content/backtracking/index.mdx
new file mode 100644
index 0000000..46de4ce
--- /dev/null
+++ b/apps/docs/content/backtracking/index.mdx
@@ -0,0 +1,163 @@
+---
+title: Backtracking
+description: 'Backtracking is a depth-first search technique that builds a solution step by step and abandons (undoes) a partial choice as soon as it can’t lead to a valid complete solution.'
+hidden: true
+---
+
+## What it is
+
+Backtracking explores possible paths to a solution one step at a time. When a path reaches a dead end, you undo the last step and try a different option. Think of every problem as a decision tree. The root is an empty answer. Each level is a decision. Each branch is one option.
+
+## When to use it
+
+Use backtracking when you must generate **all** valid solutions or evaluate **all** combinations. Do not use it when you need only one solution or the optimal solution. For those, use greedy or dynamic programming. Backtracking has exponential time complexity.
+
+## The four components
+
+Every backtracking problem has the same parts:
+
+1. **Base case** — when to save the current path and stop.
+2. **Choices** — the options at each step.
+3. **Constraints** — the rules that reject an invalid path early.
+4. **Backtrack step** — undo the last choice and try the next one.
+
+## The template
+
+```python
+def solve(data):
+ result = []
+ path = []
+
+ def backtrack(index):
+ # 1. Base case
+ if is_complete(index, path):
+ result.append(path[:]) # copy — lists are passed by reference
+ return
+
+ # 2. Choices
+ for choice in get_choices(index, data):
+ # 3. Constraints
+ if not is_valid(choice, path):
+ continue
+
+ path.append(choice) # make the choice
+ backtrack(index + 1) # explore
+ path.pop() # 4. Backtrack
+
+ backtrack(0)
+ return result
+```
+
+## Steps to apply the template
+
+1. Draw the decision tree for a small input. Name each level and each branch.
+2. Write the base case. Ask: when is the path complete?
+3. Write the choices. Ask: what can I add at this level?
+4. Write the constraints. Ask: what makes a path invalid? Reject it before recursion.
+5. Add the backtrack step. Pop what you appended.
+6. Copy the path when you save it. Never append the same list reference.
+
+## Four problems, one template
+
+### Subsets
+
+Choice: include or skip each number. No constraint. Base case: index equals list length.
+
+```python
+def subsets(nums):
+ result, path = [], []
+
+ def backtrack(i):
+ if i == len(nums):
+ result.append(path[:])
+ return
+ path.append(nums[i]) # include
+ backtrack(i + 1)
+ path.pop()
+ backtrack(i + 1) # skip
+
+ backtrack(0)
+ return result
+```
+
+### Permutations
+
+Same choices as subsets. Constraint: do not reuse a number already in the path. Base case: path length equals list length.
+
+```python
+def permute(nums):
+ result, path = [], []
+ used = [False] * len(nums)
+
+ def backtrack():
+ if len(path) == len(nums):
+ result.append(path[:])
+ return
+ for i in range(len(nums)):
+ if used[i]:
+ continue
+ used[i] = True
+ path.append(nums[i])
+ backtrack()
+ path.pop()
+ used[i] = False
+
+ backtrack()
+ return result
+```
+
+### Combinations
+
+Same as subsets. Change one line: save the path only when its length equals `k`.
+
+```python
+def combine(n, k):
+ result, path = [], []
+
+ def backtrack(start):
+ if len(path) == k:
+ result.append(path[:])
+ return
+ for i in range(start, n + 1):
+ path.append(i)
+ backtrack(i + 1)
+ path.pop()
+
+ backtrack(1)
+ return result
+```
+
+### N-Queens
+
+Choice: which column to place the queen in the current row. Constraint: no shared column or diagonal. Base case: `n` queens placed. Backtrack: remove the last queen.
+
+```python
+def solve_n_queens(n):
+ result, cols = [], []
+ used_cols, diag1, diag2 = set(), set(), set()
+
+ def backtrack(row):
+ if row == n:
+ result.append(cols[:])
+ return
+ for col in range(n):
+ if col in used_cols or row - col in diag1 or row + col in diag2:
+ continue
+ cols.append(col)
+ used_cols.add(col); diag1.add(row - col); diag2.add(row + col)
+ backtrack(row + 1)
+ cols.pop()
+ used_cols.remove(col); diag1.remove(row - col); diag2.remove(row + col)
+
+ backtrack(0)
+ return result
+```
+
+## Common mistakes
+
+- You append the `path` list itself instead of a copy. The result fills with empty lists.
+- You forget to pop. The path grows and never resets.
+- You check constraints after recursion instead of before. You waste time on dead paths.
+- You use backtracking when you need only one answer. Use greedy or DP instead.
+
+
diff --git a/apps/docs/content/backtracking/meta.ts b/apps/docs/content/backtracking/meta.ts
new file mode 100644
index 0000000..5acd18c
--- /dev/null
+++ b/apps/docs/content/backtracking/meta.ts
@@ -0,0 +1,3 @@
+import { defineMeta } from "blume";
+
+export default defineMeta({ title: "Backtracking", order: 20 });
diff --git a/work/1/Medium/Array/39.combination-sum.py b/work/1/Medium/Array/39.combination-sum.py
new file mode 100644
index 0000000..6f37cc0
--- /dev/null
+++ b/work/1/Medium/Array/39.combination-sum.py
@@ -0,0 +1,75 @@
+"""
+39. Combination Sum
+Difficulty: Medium
+https://leetcode.com/problems/combination-sum/
+
+──────────────────────────────────────────────────
+
+Given an array of distinct integers candidates and a target integer
+target, return a list of all unique combinations of candidates where
+the chosen numbers sum to target. You may return the combinations in
+any order.
+
+The same number may be chosen from candidates an unlimited number of
+times. Two combinations are unique if the frequency of at least one of
+the chosen numbers is different.
+
+The test cases are generated such that the number of unique
+combinations that sum up to target is less than 150 combinations for
+the given input.
+
+
+
+Example 1:
+
+Input: candidates = [2,3,6,7], target = 7
+Output: [[2,2,3],[7]]
+Explanation:
+2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used
+multiple times.
+7 is a candidate, and 7 = 7.
+These are the only two combinations.
+
+Example 2:
+
+Input: candidates = [2,3,5], target = 8
+Output: [[2,2,2,2],[2,3,3],[3,5]]
+
+Example 3:
+
+Input: candidates = [2], target = 1
+Output: []
+
+
+
+Constraints:
+
+ • 1 <= candidates.length <= 30
+
+ • 2 <= candidates[i] <= 40
+
+ • All elements of candidates are distinct.
+
+ • 1 <= target <= 40
+"""
+
+
+class Solution:
+ def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
+ candidates.sort()
+ result, path = [], []
+
+ def backtrack(start, remaining):
+ if remaining == 0:
+ result.append(path[:])
+ return
+ for i in range(start, len(candidates)):
+ if candidates[i] > remaining:
+ break
+
+ path.append(candidates[i])
+ backtrack(i, remaining - candidates[i])
+ path.pop()
+
+ backtrack(0, target)
+ return result
diff --git a/work/1/Medium/Array/46.permutations.py b/work/1/Medium/Array/46.permutations.py
new file mode 100644
index 0000000..0483808
--- /dev/null
+++ b/work/1/Medium/Array/46.permutations.py
@@ -0,0 +1,59 @@
+"""
+46. Permutations
+Difficulty: Medium
+https://leetcode.com/problems/permutations/
+
+──────────────────────────────────────────────────
+
+Given an array nums of distinct integers, return all the possible
+permutations. You can return the answer in any order.
+
+
+
+Example 1:
+
+Input: nums = [1,2,3]
+Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+
+Example 2:
+
+Input: nums = [0,1]
+Output: [[0,1],[1,0]]
+
+Example 3:
+
+Input: nums = [1]
+Output: [[1]]
+
+
+
+Constraints:
+
+ • 1 <= nums.length <= 6
+
+ • -10 <= nums[i] <= 10
+
+ • All the integers of nums are unique.
+"""
+
+
+class Solution:
+ def permute(self, nums: list[int]) -> list[list[int]]:
+ result, path = [], []
+ used = [False] * len(nums)
+
+ def backtrack():
+ if len(path) == len(nums):
+ result.append(path[:])
+ return
+ for i in range(len(nums)):
+ if used[i]:
+ continue
+ used[i] = True
+ path.append(nums[i])
+ backtrack()
+ path.pop()
+ used[i] = False
+
+ backtrack()
+ return result
diff --git a/work/1/Medium/Array/78.subsets.py b/work/1/Medium/Array/78.subsets.py
new file mode 100644
index 0000000..9872e53
--- /dev/null
+++ b/work/1/Medium/Array/78.subsets.py
@@ -0,0 +1,50 @@
+"""
+78. Subsets
+Difficulty: Medium
+https://leetcode.com/problems/subsets/
+
+──────────────────────────────────────────────────
+
+Given an integer array nums of unique elements, return all possible
+subsets (the power set).
+
+The solution set must not contain duplicate subsets. Return the
+solution in any order.
+
+
+
+Example 1:
+
+Input: nums = [1,2,3]
+Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
+
+Example 2:
+
+Input: nums = [0]
+Output: [[],[0]]
+
+
+
+Constraints:
+
+ • 1 <= nums.length <= 10
+
+ • -10 <= nums[i] <= 10
+
+ • All the numbers of nums are unique.
+"""
+
+
+class Solution:
+ def subsets(self, nums: list[int]) -> list[list[int]]:
+ res = []
+
+ def backtrack(i, path):
+ res.append(path[:])
+ for num_idx in range(i, len(nums)):
+ path.append(nums[num_idx])
+ backtrack(num_idx + 1, path)
+ path.pop()
+
+ backtrack(0, [])
+ return res