一键导入
algo-greedy
Greedy algorithms — exchange-argument proofs, when greedy beats DP, classic patterns (interval scheduling, Huffman, scheduling).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Greedy algorithms — exchange-argument proofs, when greedy beats DP, classic patterns (interval scheduling, Huffman, scheduling).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | algo-greedy |
| description | Greedy algorithms — exchange-argument proofs, when greedy beats DP, classic patterns (interval scheduling, Huffman, scheduling). |
| when-to-use | Interval scheduling, activity selection, minimum-spanning-tree weights, Huffman codes, fractional knapsack, scheduling with deadlines. |
Greedy algorithms make the locally optimal choice at every step and never reconsider. They are the right tool when an "exchange argument" works: any optimal solution can be transformed into the greedy solution without losing optimality.
O(n log n) sort
step.O((V + E) log V) or O(n log n).O(n).def max_non_overlapping(intervals: list[tuple[int, int]]) -> int:
"""Maximum number of non-overlapping intervals (start, end)."""
intervals.sort(key=lambda iv: iv[1]) # sort by end
count = 0
end = float("-inf")
for s, e in intervals:
if s >= end:
count += 1
end = e
return count
The exchange-argument proof: pick any optimal schedule's first
interval O; replace it with the earliest-ending interval G.
G ends no later than O, so the rest of the schedule still
fits. Repeat. The greedy schedule has at least as many intervals.
import heapq
def huffman_cost(weights: list[int]) -> int:
"""Total cost of an optimal binary prefix code (sum of code lengths × freq)."""
heap = list(weights)
heapq.heapify(heap)
total = 0
while len(heap) > 1:
a = heapq.heappop(heap)
b = heapq.heappop(heap)
total += a + b
heapq.heappush(heap, a + b)
return total
The merging-pair argument: in any optimal prefix tree, the two lowest-frequency leaves are siblings at the deepest level. Merging them into one node reduces the problem by 1, and the optimal solution to the sub-problem extends to the original.
function canJump(nums) {
let reach = 0;
for (let i = 0; i < nums.length; i++) {
if (i > reach) return false; // cannot reach i
reach = Math.max(reach, i + nums[i]); // extend horizon
}
return true;
}
reach is the invariant: "farthest index reachable from the
prefix [0..i]". Each step either extends the horizon or fails.
[1, 3, 4],
target 6 — greedy picks 4+1+1 (3 coins), DP picks 3+3 (2 coins).When the problem says "minimum number of X" or "maximum number of non-conflicting Y", greedy is a strong first guess. When it says "minimum cost to achieve goal Z", DP is the safer first guess.
Breadth-first search — shortest path on unweighted graphs, level-order traversal, and the `visited` discipline that prevents O(2^n) blowups.
Binary search invariants, half-open intervals, and the `lo<hi` template that beats off-by-one bugs.
Depth-first search — recursive vs iterative, recursion-depth gotchas, three-color cycle detection, topological sort.
Dynamic programming — state design, memoization vs tabulation, dimension-reduction, and when DP is the wrong tool.
Pick the right traversal — BFS for unweighted shortest path, Dijkstra for weighted, A* for goal-directed, 0/1-BFS for binary weights.
Hash maps and sets — when O(1) lookup pays off, hash collisions, frozen keys, and hashing custom types.