Skip to content

Commit 77ca2ec

Browse files
lufftwclaude
andcommitted
feat(benchmarks): Add Top 20 spotlight and full benchmark table
- Update spotlight to show Top 20 (was Top 15) - Add link to full benchmark data in spotlight section - Create benchmarks-full.md with all 83 multi-solution problems - Add back-link from full table to spotlight - Include Time/Space complexity in full table Structure: - benchmarks.md: Top 20 spotlight (concise) - benchmarks-full.md: All 83 problems (detailed) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0a571b4 commit 77ca2ec

3 files changed

Lines changed: 231 additions & 7 deletions

File tree

docs/benchmarks-full.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Full Benchmark Data (n=5000)
2+
3+
[← 返回 Spotlight](benchmarks.md#large-n-spotlight-n5000)
4+
5+
**83** 題有多解法可比較。
6+
7+
## All Problems
8+
9+
| # | Problem | Fast | Slow | Speedup | Time Complexity | Space Complexity |
10+
|--:|---------|------|------|--------:|-----------------|------------------|
11+
| 0010 | Regex Matching | Top-down Memo (0.08ms) | Bottom-up DP (5.3s) | 62,000× | O(mn) vs O(mn) | O(m*n) vs O(m*n) |
12+
| 0044 | Wildcard Match | Greedy Backtrack (1.4ms) | 2D DP Table (10.0s) | 7,000× | O(mn) vs O(mn) | O(1) vs O(m*n) |
13+
| 0011 | Container Water | Two Pointers (0.75ms) | Nested Loops (4.9s) | 7,000× | O(n) vs O(n^2) | O(1) vs O(1) |
14+
| 0121 | Buy Sell Stock | Running Min (2.0ms) | Nested Loops (3.1s) | 2,000× | O(n) vs O(n²) | O(1) vs O(1) |
15+
| 0416 | Partition Sum | 2D DP Table (0.08ms) | 1D DP Space-Opt (96.6ms) | 1,000× | O(n target) vs O(n target) | O(n * target) vs O(target) |
16+
| 0016 | 3Sum Closest | Two Ptr+Prune (1.1ms) | Two Ptr Basic (1.4s) | 1,000× | O(n²) vs O(n²) | O(1) vs O(1) |
17+
| 0435 | Non-Overlap Intv | Greedy Sort (5.0ms) | DP Array (3.1s) | 617× | O(n log n) vs O(n²) | O(1) vs O(n) |
18+
| 0001 | Two Sum | Hash Map (0.66ms) | Nested Loops (70.1ms) | 106× | O(n) vs O(n²) | O(n) vs O(1) |
19+
| 0494 | Target Sum | DP Transform (0.04ms) | Memoization (3.2ms) | 73× | O(n target) vs O(n sum) | O(target) vs O(n * sum) |
20+
| 0875 | Koko Bananas | Binary Search (14.6ms) | Linear Search (1.1s) | 72× | O(n log m) vs O(n × m) | O(1) vs O(1) |
21+
| 2104 | Sum Of Subarray | Stack (4.5ms) | Brute (305.5ms) | 68× | O(n) vs O(n^2) | O(n) vs O(1) |
22+
| 1011 | Capacity To Ship | Default (10.3ms) | Linear Search (343.8ms) | 33× | O(n log S) vs O(n S) | O(1) vs O(1) |
23+
| 0125 | Valid Palindrome | Default (0.03ms) | Filtered Pointe (0.80ms) | 23× | O(n) vs O(n) | O(1) vs O(n) |
24+
| 0459 | Repeated Substri | Concatenation (0.06ms) | Default (0.97ms) | 17× | O(n) vs O(n) | O(n) vs O(n) |
25+
| 0496 | Next Greater Ele | Default (0.73ms) | Brute (9.4ms) | 13× | O(n + m) vs O(m n) | O(n) vs O(1) |
26+
| 0055 | Jump Game | Greedy (1.7ms) | DP Array (10.9ms) || O(n) vs O(n^2) | O(1) vs O(n) |
27+
| 1392 | Longest Happy Pr | Default (1.5ms) | Rolling Hash (7.5ms) || O(n) vs O(n) | O(n) vs O(1) |
28+
| 0110 | Balanced Binary | Default (7.7ms) | Top Down (35.6ms) || O(n) vs O(n²) | O(h) vs O(h) |
29+
| 1094 | Car Pooling | Difference (5.4ms) | Events (18.1ms) || O(n + m) vs O(n log n) | O(m) vs O(n) |
30+
| 0200 | Number Of Island | Dfs (3.1ms) | Union Find (9.7ms) || O(mn) vs O(mn α(mn)) | O(m*n) vs O(m*n) |
31+
| 0990 | Satisfiability O | Dfs (1.6ms) | Default (4.5ms) || O(n + 26) vs O(n × α(26)) | O(26) vs O(1) |
32+
| 0141 | Linked List Cycl | Default (3.1ms) | Hashset (8.3ms) || O(n) vs O(n) | O(1) vs O(n) |
33+
| 0023 | Merge K Lists | Heap Merge (17.3ms) | Sequential (46.4ms) ||||
34+
| 0213 | House Robber Ii | Default (0.10ms) | Memoization (0.25ms) || O(n) vs O(n) | O(1) vs O(n) |
35+
| 0253 | Meeting Rooms Ii | Default (7.6ms) | Sweep (17.6ms) || O(n log n) vs O(n log n) | O(n) vs O(n) |
36+
| 0680 | Valid Palindrome | Two Pointers (0.03ms) | Iterative (0.08ms) || O(n) vs O(n) | O(1) vs O(1) |
37+
| 0033 | Search Rotated | Binary Search (0.48ms) | Linear Scan (1.1ms) || O(log n) vs O(n) | O(1) vs O(1) |
38+
| 0209 | Minimum Size Sub | Sliding Window (1.6ms) | Binary Search (3.5ms) || O(n) vs O(n log n) | O(1) vs O(n) |
39+
| 0283 | Move Zeroes | Two Pointers (1.5ms) | Swap (3.1ms) || O(n) vs O(n) | O(1) vs O(1) |
40+
| 0042 | Trapping Rain | Two Pointers (1.8ms) | Prefix Arrays (3.7ms) || O(n) vs O(n) | O(1) vs O(n) |
41+
| 0198 | House Robber | Default (0.07ms) | Memoization (0.15ms) || O(n) vs O(n) | O(1) vs O(n) |
42+
| 0743 | Network Delay Ti | Bellman Ford (9.7ms) | Default (19.4ms) || O(V × E) vs O((V+E) log V) | O(V) vs O(V+E) |
43+
| 0905 | Sort Array By Pa | Opposite Pointe (2.2ms) | Writer (4.2ms) || O(n) vs O(n) | O(1) vs O(1) |
44+
| 0322 | Coin Change | Bfs (3.6ms) | Default (6.9ms) || O(n amount) vs O(n amount) | O(amount) vs O(amount) |
45+
| 0202 | Happy Number | Default (0.03ms) | Hashset (0.06ms) || O(log n) vs O(log n) | O(1) vs O(log n) |
46+
| 0315 | Count Of Smaller | Default (16.6ms) | Merge Sort (29.7ms) || O(n log n) vs O(n log n) | O(n) vs O(n) |
47+
| 0028 | Find The Index O | Default (0.68ms) | Rabin Karp (1.2ms) || O(m+n) vs O(m+n) | O(n) vs O(1) |
48+
| 0214 | Shortest Palindr | Default (1.6ms) | Rolling Hash (2.8ms) || O(n) vs O(n) | O(n) vs O(1) |
49+
| 0516 | Longest Palindro | Interval Dp (6.5s) | Default (11.3s) || O(n^2) vs O(n^2) | O(n^2) vs O(n^2) |
50+
| 0070 | Climbing Stairs | Dp Space Optimi (0.03ms) | Memoization (0.05ms) || O(n) vs O(n) | O(1) vs O(n) |
51+
| 1499 | Max Value Of Equ | Default (7.8ms) | Deque (13.0ms) || O(n) vs O(n) | O(n) vs O(n) |
52+
| 0218 | The Skyline Prob | Default (14.9ms) | Heap (24.4ms) || O(n log n) vs O(n log n) | O(n) vs O(n) |
53+
| 0134 | Gas Station | Default (1.6ms) | Greedy (2.4ms) || O(n) vs O(n) | O(1) vs O(1) |
54+
| 0994 | Rotting Oranges | Simulation (0.16ms) | Bfs (0.24ms) || O((mn)²) vs O(mn) | O(m*n) vs O(m*n) |
55+
| 0084 | Largest Rectangl | Default (2.9ms) | Twopass (4.6ms) || O(n) vs O(n) | O(n) vs O(n) |
56+
| 0307 | Range Sum Query | Default (38.2ms) | Bit (58.2ms) ||||
57+
| 0015 | 3Sum | Default (1.5s) | Hash (2.2s) || O(n²) vs O(n²) | O(1) vs O(n) |
58+
| 0721 | Accounts Merge | Union Find (0.09ms) | Dfs (0.13ms) || O(n × k × α(n)) vs O(n × k) | O(n × k) vs O(n × k) |
59+
| 0142 | Linked List Cycl | Default (2.8ms) | Hashset (4.1ms) || O(n) vs O(n) | O(1) vs O(n) |
60+
| 0684 | Redundant Connec | Union Find (0.08ms) | Dfs (0.11ms) || O(n × α(n)) vs O(n²) | O(n) vs O(n) |
61+
| 0003 | Longest Substrin | Default (1.4ms) | Set (2.0ms) || O(n) vs O(n) | O(min(n,σ)) vs O(min(n,σ)) |
62+
| 1438 | Longest Continuo | Two Deques (6.9ms) | Default (9.3ms) || O(n) vs O(n) | O(n) vs O(n) |
63+
| 0295 | Find Median From | Default (7.7ms) | Sorted List (10.1ms) ||||
64+
| 0746 | Min Cost Climbin | Dp Space Optimi (0.52ms) | Default (0.69ms) || O(n) vs O(n) | O(1) vs O(1) |
65+
| 0542 | 01 Matrix | Dp (6.1ms) | Default (8.0ms) || O(mn) vs O(mn) | O(1) vs O(m*n) |
66+
| 1029 | Two City Schedul | Default (5.9ms) | Greedy (7.6ms) || O(n log n) vs O(n log n) | O(1) vs O(1) |
67+
| 0076 | Minimum Window S | Default (2.6ms) | Sliding Window (3.4ms) || O(|s| + |t|) vs O(|s| + |t|) | O(|t|) vs O(|s|) |
68+
| 0085 | Maximal Rectangl | Default (2.2ms) | Dp (2.8ms) || O(rows cols) vs O(rows cols) | O(cols) vs O(cols) |
69+
| 0876 | Middle Of The Li | Default (3.3ms) | Two Pass (4.2ms) || O(n) vs O(n) | O(1) vs O(1) |
70+
| 0503 | Next Greater Ele | Default (3.3ms) | Concat (4.2ms) || O(n) vs O(n) | O(n) vs O(n) |
71+
| 0080 | Remove Duplicate | Counter (1.6ms) | Default (2.0ms) || O(n) vs O(n) | O(1) vs O(1) |
72+
| 0072 | Edit Distance | Space Optimized (11.1s) | Default (13.7s) || O(mn) vs O(mn) | O(min(m,n)) vs O(m*n) |
73+
| 0907 | Sum Of Subarray | Default (5.3ms) | Contribution (6.4ms) || O(n) vs O(n) | O(n) vs O(n) |
74+
| 0027 | Remove Element | Two Ends (1.1ms) | Two Pointers (1.3ms) || O(n) vs O(n) | O(1) vs O(1) |
75+
| 0977 | Squares Of A Sor | Two Pointers (2.2ms) | Default (2.6ms) || O(n) vs O(n) | O(n) vs O(n) |
76+
| 0135 | Candy | Default (2.1ms) | Two Pass (2.5ms) || O(n) vs O(n) | O(n) vs O(n) |
77+
| 0162 | Find Peak Elemen | Linear Scan (0.16ms) | Default (0.19ms) || O(n) vs O(log n) | O(1) vs O(1) |
78+
| 0739 | Daily Temperatur | Backward (2.2ms) | Default (2.5ms) || O(n) vs O(n) | O(1) vs O(n) |
79+
| 1143 | Longest Common S | Space Optimized (12.5s) | Default (14.4s) || O(mn) vs O(mn) | O(min(m,n)) vs O(m*n) |
80+
| 0239 | Sliding Window M | Default (3.3ms) | Deque (3.8ms) || O(n) vs O(n) | O(k) vs O(k) |
81+
| 0327 | Count Of Range S | Merge Sort (25.4ms) | Default (27.9ms) || O(n log n) vs O(n log n) | O(n) vs O(n) |
82+
| 0215 | Kth Largest Elem | Quickselect (1.8ms) | Heap (2.0ms) || O(n) vs O(n log k) | O(1) vs O(k) |
83+
| 0026 | Remove Duplicate | Default (0.86ms) | Enumerate (0.93ms) || O(n) vs O(n) | O(1) vs O(1) |
84+
| 0862 | Shortest Subarra | Default (2.9ms) | Deque (3.1ms) || O(n) vs O(n) | O(n) vs O(n) |
85+
| 0088 | Merge Sorted Arr | Backward (1.9ms) | Forward (2.0ms) || O(m+n) vs O(m+n) | O(1) vs O(m) |
86+
| 0056 | Merge Intervals | Sort Merge (5.2ms) | Default (5.4ms) || O(n log n) vs O(n log n) | O(n) vs O(n) |
87+
| 0968 | Binary Tree Came | Dp (85.0ms) | Default (89.2ms) || O(n) vs O(n) | O(h) vs O(h) |
88+
| 0045 | Jump Game Ii | Default (1.6ms) | Greedy (1.7ms) || O(n) vs O(n) | O(1) vs O(1) |
89+
| 0518 | Coin Change 2 | Default (2.2ms) | Dp Unbounded (2.3ms) || O(n amount) vs O(n amount) | O(amount) vs O(amount) |
90+
| 0455 | Assign Cookies | Greedy (3.3ms) | Default (3.4ms) || O(n log n + m log m) vs O(n log n + m log m) | O(1) vs O(1) |
91+
| 0075 | Sort Colors | Default (1.3ms) | Dutch Flag (1.3ms) || O(n) vs O(n) | O(1) vs O(1) |
92+
| 0337 | House Robber Iii | Default (88.6ms) | Memo (90.7ms) || O(n) vs O(n) | O(h) vs O(n) |
93+
| 0922 | Sort Array By Pa | Two Pointers (2.2ms) | Default (2.2ms) || O(n) vs O(n) | O(1) vs O(1) |
94+
95+
---
96+
97+
## Legend
98+
99+
- **Fast**: Fastest method at n=5000
100+
- **Slow**: Slowest method at n=5000
101+
- **Speedup**: How many times faster the Fast method is
102+
- **Time Complexity**: Big-O time (Fast vs Slow)
103+
- **Space Complexity**: Big-O space (Fast vs Slow)

docs/benchmarks.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,15 @@ When input size grows, algorithm choice becomes critical:
2323
| 0125 | Valid Palindrome | Default (0.03ms) | Filtered Pointe (0.80ms) | **23x** faster |
2424
| 0459 | Repeated Substring Pat | Concatenation (0.06ms) | Default (0.97ms) | **17x** faster |
2525
| 0496 | Next Greater Element I | Default (0.73ms) | Brute (9.4ms) | **13x** faster |
26+
| 0055 | Jump Game | Greedy (1.7ms) | DP Array (10.9ms) | **7x** faster |
27+
| 1392 | Longest Happy Prefix | Default (1.5ms) | Rolling Hash (7.5ms) | **5x** faster |
28+
| 0110 | Balanced Binary Tree | Default (7.7ms) | Top Down (35.6ms) | **5x** faster |
29+
| 1094 | Car Pooling | Difference (5.4ms) | Events (18.1ms) | **3x** faster |
30+
| 0200 | Number Of Islands | Dfs (3.1ms) | Union Find (9.7ms) | **3x** faster |
2631

2732
> At n=5000, the wrong algorithm choice turns **milliseconds into minutes**.
28-
> Regular Expression Matching: Memoization finishes while you blink; 2D DP takes a coffee break.
33+
34+
📊 [查看全部 Large N 數據 →](benchmarks-full.md)
2935

3036
---
3137

scripts/generate_benchmark_tables.py

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def generate_large_n_spotlight(large_n_data, top_n=10):
107107

108108
if fastest["time_n5000_ms"] > 0:
109109
ratio = slowest["time_n5000_ms"] / fastest["time_n5000_ms"]
110-
if ratio > 10: # Only include 10x+ speedups
110+
if ratio >= 2: # Only include 2x+ speedups
111111
dramatic.append({
112112
"problem": problem,
113113
"fastest_method": fastest["method"],
@@ -300,10 +300,115 @@ def format_spotlight_markdown(spotlight):
300300
f"{speedup} |"
301301
)
302302

303-
# Add interpretation
303+
# Add interpretation and link to full table
304304
lines.append("")
305305
lines.append("> At n=5000, the wrong algorithm choice turns **milliseconds into minutes**.")
306-
lines.append("> Regular Expression Matching: Memoization finishes while you blink; 2D DP takes a coffee break.")
306+
lines.append("")
307+
lines.append("📊 [查看全部 Large N 數據 →](benchmarks-full.md)")
308+
309+
return "\n".join(lines)
310+
311+
312+
def generate_all_large_n_comparisons(large_n_data, benchmark_data):
313+
"""Generate full table data for all problems with large n comparisons."""
314+
all_data = []
315+
316+
for problem, data in large_n_data.items():
317+
methods = data.get("estimate", {}).get("methods", [])
318+
if len(methods) < 2:
319+
continue
320+
321+
fastest = min(methods, key=lambda x: x["time_n5000_ms"])
322+
slowest = max(methods, key=lambda x: x["time_n5000_ms"])
323+
324+
if fastest["time_n5000_ms"] > 0:
325+
ratio = slowest["time_n5000_ms"] / fastest["time_n5000_ms"]
326+
327+
# Get complexity info
328+
fast_time_c, fast_space_c = get_complexity_from_benchmark(
329+
benchmark_data, problem, fastest["method"])
330+
slow_time_c, slow_space_c = get_complexity_from_benchmark(
331+
benchmark_data, problem, slowest["method"])
332+
333+
all_data.append({
334+
"problem": problem,
335+
"fastest_method": fastest["method"],
336+
"fastest_time": fastest["time_n5000_ms"],
337+
"slowest_method": slowest["method"],
338+
"slowest_time": slowest["time_n5000_ms"],
339+
"ratio": ratio,
340+
"fast_time_complexity": fast_time_c,
341+
"slow_time_complexity": slow_time_c,
342+
"fast_space_complexity": fast_space_c,
343+
"slow_space_complexity": slow_space_c,
344+
})
345+
346+
# Sort by ratio descending
347+
all_data.sort(key=lambda x: x["ratio"], reverse=True)
348+
return all_data
349+
350+
351+
def format_full_benchmark_markdown(all_data, benchmark_data):
352+
"""Format full benchmark data as markdown for benchmarks-full.md."""
353+
354+
def simplify_complexity(c):
355+
if " worst" in c:
356+
c = c.split(" worst")[0]
357+
if " average" in c:
358+
c = c.split(" average")[0]
359+
return c.strip()
360+
361+
lines = [
362+
"# Full Benchmark Data (n=5000)",
363+
"",
364+
"[← 返回 Spotlight](benchmarks.md#large-n-spotlight-n5000)",
365+
"",
366+
f"共 **{len(all_data)}** 題有多解法可比較。",
367+
"",
368+
"## All Problems",
369+
"",
370+
"| # | Problem | Fast | Slow | Speedup | Time Complexity | Space Complexity |",
371+
"|--:|---------|------|------|--------:|-----------------|------------------|"
372+
]
373+
374+
for d in all_data:
375+
prob_num = d["problem"].split("_")[0]
376+
prob_name = get_short_problem_name(d["problem"])
377+
fast_name = get_descriptive_method_name(d["problem"], d["fastest_method"])
378+
slow_name = get_descriptive_method_name(d["problem"], d["slowest_method"])
379+
fast_time = format_time_human(d["fastest_time"])
380+
slow_time = format_time_human(d["slowest_time"])
381+
382+
# Format speedup
383+
if d["ratio"] >= 1000:
384+
speedup = f"{d['ratio']/1000:.0f},000×"
385+
else:
386+
speedup = f"{d['ratio']:.0f}×"
387+
388+
# Format complexity
389+
fast_tc = simplify_complexity(d["fast_time_complexity"])
390+
slow_tc = simplify_complexity(d["slow_time_complexity"])
391+
time_c = f"{fast_tc} vs {slow_tc}" if fast_tc != "?" and slow_tc != "?" else "—"
392+
393+
fast_sc = d["fast_space_complexity"]
394+
slow_sc = d["slow_space_complexity"]
395+
space_c = f"{fast_sc} vs {slow_sc}" if fast_sc != "?" and slow_sc != "?" else "—"
396+
397+
lines.append(
398+
f"| {prob_num} | {prob_name} | {fast_name} ({fast_time}) | "
399+
f"{slow_name} ({slow_time}) | {speedup} | {time_c} | {space_c} |"
400+
)
401+
402+
lines.append("")
403+
lines.append("---")
404+
lines.append("")
405+
lines.append("## Legend")
406+
lines.append("")
407+
lines.append("- **Fast**: Fastest method at n=5000")
408+
lines.append("- **Slow**: Slowest method at n=5000")
409+
lines.append("- **Speedup**: How many times faster the Fast method is")
410+
lines.append("- **Time Complexity**: Big-O time (Fast vs Slow)")
411+
lines.append("- **Space Complexity**: Big-O space (Fast vs Slow)")
307412

308413
return "\n".join(lines)
309414

@@ -463,10 +568,15 @@ def main():
463568
main_rows = generate_main_table(benchmark_data)
464569
main_md = format_main_table_markdown(main_rows)
465570

466-
print("Generating spotlight...")
467-
spotlight = generate_large_n_spotlight(large_n_data, top_n=15)
571+
print("Generating spotlight (Top 20)...")
572+
spotlight = generate_large_n_spotlight(large_n_data, top_n=20)
468573
spotlight_md = format_spotlight_markdown(spotlight) if spotlight else "No large n data available yet."
469574

575+
print("Generating full large n table...")
576+
all_large_n = generate_all_large_n_comparisons(large_n_data, benchmark_data)
577+
full_benchmark_md = format_full_benchmark_markdown(all_large_n, benchmark_data)
578+
print(f" Found {len(all_large_n)} problems with multi-solution comparisons")
579+
470580
print("Generating appendix...")
471581
appendix = generate_appendix(benchmark_data)
472582
appendix_md = format_appendix_markdown(appendix)
@@ -509,11 +619,16 @@ def main():
509619
```
510620
"""
511621

512-
# Save
622+
# Save benchmarks.md
513623
output_path = PROJECT_ROOT / "docs" / "benchmarks.md"
514624
output_path.write_text(doc, encoding="utf-8")
515625
print(f"\n[DONE] Saved to {output_path}")
516626

627+
# Save benchmarks-full.md
628+
full_output_path = PROJECT_ROOT / "docs" / "benchmarks-full.md"
629+
full_output_path.write_text(full_benchmark_md, encoding="utf-8")
630+
print(f"[DONE] Saved to {full_output_path}")
631+
517632

518633
if __name__ == "__main__":
519634
main()

0 commit comments

Comments
 (0)