Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "leetcode-teacher",
|
||||||
|
"description": "Interactive LeetCode-style teacher for technical interview preparation. Generates coding playgrounds with real product challenges, teaches patterns and techniques, supports Python/TypeScript/Kotlin/Swift, and provides progressive difficulty training for data structures and algorithms.",
|
||||||
|
"version": "0.0.0-2025.11.28",
|
||||||
|
"author": {
|
||||||
|
"name": "James Rochabrun",
|
||||||
|
"email": "jamesrochabrun@gmail.com"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills/leetcode-teacher"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# leetcode-teacher
|
||||||
|
|
||||||
|
Interactive LeetCode-style teacher for technical interview preparation. Generates coding playgrounds with real product challenges, teaches patterns and techniques, supports Python/TypeScript/Kotlin/Swift, and provides progressive difficulty training for data structures and algorithms.
|
||||||
60
plugin.lock.json
Normal file
60
plugin.lock.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:jamesrochabrun/skills:leetcode-teacher",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "251940af63705b1d25992e37b6913ada62ff6c2b",
|
||||||
|
"treeHash": "dbce76ed9c086f34610a6197a93ebc7f35623665fdb71bfbc6f2baf6c63baba0",
|
||||||
|
"generatedAt": "2025-11-28T10:17:50.651804Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "leetcode-teacher",
|
||||||
|
"description": "Interactive LeetCode-style teacher for technical interview preparation. Generates coding playgrounds with real product challenges, teaches patterns and techniques, supports Python/TypeScript/Kotlin/Swift, and provides progressive difficulty training for data structures and algorithms."
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "fb005cda88da18ffa7c8e3f10c9fd371b8e9560230b1d968702cc85826b0c325"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "9e1e01757f241f2a1efc54794c6373397b454c0eae0d88730c249ebd97b9e518"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/leetcode-teacher/SKILL.md",
|
||||||
|
"sha256": "3814ee12bb2d7a76e145e00cf4fcb7300275707bb92907418ed361db3750b781"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/leetcode-teacher/references/data_structures.md",
|
||||||
|
"sha256": "aa7f7a0d8b800ae221051d78cc5b5e9ee5509db4f2cb119a90eb397810241dcf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/leetcode-teacher/references/patterns.md",
|
||||||
|
"sha256": "914ce5c58cdca6a2ea6c10a5770e731f425012a1b6fcb1f22e95b842930a4353"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/leetcode-teacher/scripts/generate_playground.sh",
|
||||||
|
"sha256": "0245b50d1b0a0bb5567b4611201009f7d777e67b84a86cc4a28b7e5d81b2033e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/leetcode-teacher/scripts/generate_problem.sh",
|
||||||
|
"sha256": "f9af6842ff5f377c66a107740b864b2bd5453ab77044486cf8bc1cd8bd7f18eb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "dbce76ed9c086f34610a6197a93ebc7f35623665fdb71bfbc6f2baf6c63baba0"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
921
skills/leetcode-teacher/SKILL.md
Normal file
921
skills/leetcode-teacher/SKILL.md
Normal file
@@ -0,0 +1,921 @@
|
|||||||
|
---
|
||||||
|
name: leetcode-teacher
|
||||||
|
description: Interactive LeetCode-style teacher for technical interview preparation. Generates coding playgrounds with real product challenges, teaches patterns and techniques, supports Python/TypeScript/Kotlin/Swift, and provides progressive difficulty training for data structures and algorithms.
|
||||||
|
---
|
||||||
|
|
||||||
|
# LeetCode Teacher
|
||||||
|
|
||||||
|
An interactive technical interview preparation teacher that generates engaging coding playgrounds with real-world product challenges, pattern recognition training, and multi-language support.
|
||||||
|
|
||||||
|
## What This Skill Does
|
||||||
|
|
||||||
|
Transforms technical interview prep into interactive, practical experiences:
|
||||||
|
- **Interactive Code Playgrounds** - Browser-based coding environments with instant feedback
|
||||||
|
- **Multi-Language Support** - Python, TypeScript, Kotlin, Swift
|
||||||
|
- **Real Product Challenges** - Practical scenarios from real companies
|
||||||
|
- **Pattern Recognition** - Learn the 20 essential coding patterns
|
||||||
|
- **Progressive Difficulty** - Easy → Medium → Hard → Expert
|
||||||
|
- **Instant Feedback** - Run tests in real-time with detailed explanations
|
||||||
|
- **Technique Teaching** - Master problem-solving approaches
|
||||||
|
|
||||||
|
## Why This Skill Matters
|
||||||
|
|
||||||
|
**Traditional LeetCode practice:**
|
||||||
|
- Abstract, disconnected problems
|
||||||
|
- No pattern recognition guidance
|
||||||
|
- Trial and error approach
|
||||||
|
- Intimidating for beginners
|
||||||
|
- Limited language options
|
||||||
|
|
||||||
|
**With this skill:**
|
||||||
|
- Real product scenarios
|
||||||
|
- Pattern-based learning
|
||||||
|
- Guided problem-solving
|
||||||
|
- Progressive difficulty curve
|
||||||
|
- Multi-language practice
|
||||||
|
- Interactive, fun interface
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
### 1. Pattern-First Learning
|
||||||
|
- Recognize problem patterns
|
||||||
|
- Apply proven templates
|
||||||
|
- Build intuition through practice
|
||||||
|
- Master one pattern at a time
|
||||||
|
|
||||||
|
### 2. Real Product Context
|
||||||
|
- Instagram feed ranking
|
||||||
|
- Uber trip matching
|
||||||
|
- Netflix recommendation
|
||||||
|
- Slack message search
|
||||||
|
- Amazon inventory management
|
||||||
|
|
||||||
|
### 3. Progressive Difficulty
|
||||||
|
- Start with fundamentals
|
||||||
|
- Build complexity gradually
|
||||||
|
- Unlock advanced patterns
|
||||||
|
- Track skill progression
|
||||||
|
|
||||||
|
### 4. Multi-Language Mastery
|
||||||
|
- Practice in your target language
|
||||||
|
- Compare implementations
|
||||||
|
- Learn language-specific tricks
|
||||||
|
- Interview in any language
|
||||||
|
|
||||||
|
### 5. Interactive Learning
|
||||||
|
- Write code in browser
|
||||||
|
- Run tests instantly
|
||||||
|
- Get hints when stuck
|
||||||
|
- See optimal solutions
|
||||||
|
- Track progress
|
||||||
|
|
||||||
|
## Problem Patterns Covered
|
||||||
|
|
||||||
|
### Array & String Patterns
|
||||||
|
|
||||||
|
**1. Two Pointers**
|
||||||
|
```
|
||||||
|
Pattern: Use two pointers to scan array
|
||||||
|
Use when: Need to find pairs, triplets, or subarrays
|
||||||
|
Example: "Find Instagram users who like each other"
|
||||||
|
Complexity: O(n) time, O(1) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Sliding Window**
|
||||||
|
```
|
||||||
|
Pattern: Maintain a window that slides through array
|
||||||
|
Use when: Need to find subarray with certain property
|
||||||
|
Example: "Find trending topics in last N tweets"
|
||||||
|
Complexity: O(n) time, O(k) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Fast & Slow Pointers**
|
||||||
|
```
|
||||||
|
Pattern: Two pointers moving at different speeds
|
||||||
|
Use when: Detect cycles, find middle element
|
||||||
|
Example: "Detect circular dependency in package manager"
|
||||||
|
Complexity: O(n) time, O(1) space
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tree & Graph Patterns
|
||||||
|
|
||||||
|
**4. Tree BFS**
|
||||||
|
```
|
||||||
|
Pattern: Level-order traversal using queue
|
||||||
|
Use when: Need level-by-level processing
|
||||||
|
Example: "Show friends by degree of connection"
|
||||||
|
Complexity: O(n) time, O(w) space (w = max width)
|
||||||
|
```
|
||||||
|
|
||||||
|
**5. Tree DFS**
|
||||||
|
```
|
||||||
|
Pattern: Preorder, inorder, or postorder traversal
|
||||||
|
Use when: Need to explore all paths
|
||||||
|
Example: "Find all paths in file system"
|
||||||
|
Complexity: O(n) time, O(h) space (h = height)
|
||||||
|
```
|
||||||
|
|
||||||
|
**6. Graph BFS**
|
||||||
|
```
|
||||||
|
Pattern: Explore neighbors level by level
|
||||||
|
Use when: Shortest path, level-based exploration
|
||||||
|
Example: "Find shortest connection path on LinkedIn"
|
||||||
|
Complexity: O(V + E) time, O(V) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**7. Graph DFS**
|
||||||
|
```
|
||||||
|
Pattern: Explore as far as possible before backtracking
|
||||||
|
Use when: Path finding, cycle detection
|
||||||
|
Example: "Detect circular references in social graph"
|
||||||
|
Complexity: O(V + E) time, O(V) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**8. Topological Sort**
|
||||||
|
```
|
||||||
|
Pattern: Order nodes by dependencies
|
||||||
|
Use when: Task scheduling, build systems
|
||||||
|
Example: "Order courses based on prerequisites"
|
||||||
|
Complexity: O(V + E) time, O(V) space
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dynamic Programming Patterns
|
||||||
|
|
||||||
|
**9. 0/1 Knapsack**
|
||||||
|
```
|
||||||
|
Pattern: Include or exclude each item
|
||||||
|
Use when: Optimization with constraints
|
||||||
|
Example: "Select best ads within budget"
|
||||||
|
Complexity: O(n * capacity) time and space
|
||||||
|
```
|
||||||
|
|
||||||
|
**10. Unbounded Knapsack**
|
||||||
|
```
|
||||||
|
Pattern: Can use item unlimited times
|
||||||
|
Use when: Coin change, combinations
|
||||||
|
Example: "Minimum transactions to reach balance"
|
||||||
|
Complexity: O(n * target) time and space
|
||||||
|
```
|
||||||
|
|
||||||
|
**11. Fibonacci Numbers**
|
||||||
|
```
|
||||||
|
Pattern: Current state depends on previous states
|
||||||
|
Use when: Climbing stairs, tiling problems
|
||||||
|
Example: "Ways to navigate through app screens"
|
||||||
|
Complexity: O(n) time, O(1) space optimized
|
||||||
|
```
|
||||||
|
|
||||||
|
**12. Longest Common Subsequence**
|
||||||
|
```
|
||||||
|
Pattern: Compare two sequences
|
||||||
|
Use when: Diff tools, edit distance
|
||||||
|
Example: "Find similar code snippets"
|
||||||
|
Complexity: O(m * n) time and space
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other Essential Patterns
|
||||||
|
|
||||||
|
**13. Modified Binary Search**
|
||||||
|
```
|
||||||
|
Pattern: Binary search on sorted or rotated array
|
||||||
|
Use when: Search in O(log n)
|
||||||
|
Example: "Find version when bug was introduced"
|
||||||
|
Complexity: O(log n) time, O(1) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**14. Top K Elements**
|
||||||
|
```
|
||||||
|
Pattern: Use heap to track K largest/smallest
|
||||||
|
Use when: Finding top items
|
||||||
|
Example: "Get top K trending hashtags"
|
||||||
|
Complexity: O(n log k) time, O(k) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**15. K-Way Merge**
|
||||||
|
```
|
||||||
|
Pattern: Merge K sorted arrays/lists
|
||||||
|
Use when: Combining sorted data
|
||||||
|
Example: "Merge activity feeds from K users"
|
||||||
|
Complexity: O(n log k) time, O(k) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**16. Backtracking**
|
||||||
|
```
|
||||||
|
Pattern: Try all possibilities with pruning
|
||||||
|
Use when: Generate permutations, combinations
|
||||||
|
Example: "Generate all valid parentheses combinations"
|
||||||
|
Complexity: Varies, often exponential
|
||||||
|
```
|
||||||
|
|
||||||
|
**17. Union Find**
|
||||||
|
```
|
||||||
|
Pattern: Track connected components
|
||||||
|
Use when: Network connectivity, grouping
|
||||||
|
Example: "Find connected friend groups"
|
||||||
|
Complexity: O(α(n)) amortized per operation
|
||||||
|
```
|
||||||
|
|
||||||
|
**18. Intervals**
|
||||||
|
```
|
||||||
|
Pattern: Merge, insert, or find overlapping intervals
|
||||||
|
Use when: Calendar scheduling, time ranges
|
||||||
|
Example: "Find free meeting slots"
|
||||||
|
Complexity: O(n log n) time, O(n) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**19. Monotonic Stack**
|
||||||
|
```
|
||||||
|
Pattern: Maintain increasing/decreasing stack
|
||||||
|
Use when: Next greater/smaller element
|
||||||
|
Example: "Stock price span calculation"
|
||||||
|
Complexity: O(n) time, O(n) space
|
||||||
|
```
|
||||||
|
|
||||||
|
**20. Trie**
|
||||||
|
```
|
||||||
|
Pattern: Prefix tree for string operations
|
||||||
|
Use when: Autocomplete, prefix matching
|
||||||
|
Example: "Implement search autocomplete"
|
||||||
|
Complexity: O(m) time per operation (m = word length)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Real Product Challenge Examples
|
||||||
|
|
||||||
|
### Easy Level
|
||||||
|
|
||||||
|
**Instagram: Like Counter**
|
||||||
|
```
|
||||||
|
Real Scenario: Count how many times user's posts were liked today
|
||||||
|
Pattern: Hash Map
|
||||||
|
Data Structure: Dictionary/HashMap
|
||||||
|
Languages: Python, TypeScript, Kotlin, Swift
|
||||||
|
```
|
||||||
|
|
||||||
|
**Slack: Unread Messages**
|
||||||
|
```
|
||||||
|
Real Scenario: Find first unread message in channel
|
||||||
|
Pattern: Linear Search with Flag
|
||||||
|
Data Structure: Array
|
||||||
|
Teaches: Early termination
|
||||||
|
```
|
||||||
|
|
||||||
|
**Uber: Calculate Fare**
|
||||||
|
```
|
||||||
|
Real Scenario: Compute trip cost based on distance and time
|
||||||
|
Pattern: Simple Calculation
|
||||||
|
Data Structure: Numbers
|
||||||
|
Teaches: Math operations, rounding
|
||||||
|
```
|
||||||
|
|
||||||
|
### Medium Level
|
||||||
|
|
||||||
|
**Netflix: Top N Recommendations**
|
||||||
|
```
|
||||||
|
Real Scenario: Find top N movies by rating
|
||||||
|
Pattern: Top K Elements (Heap)
|
||||||
|
Data Structure: Priority Queue
|
||||||
|
Teaches: Heap operations, partial sorting
|
||||||
|
```
|
||||||
|
|
||||||
|
**Amazon: Inventory Management**
|
||||||
|
```
|
||||||
|
Real Scenario: Find products running low in stock
|
||||||
|
Pattern: Filtering with Threshold
|
||||||
|
Data Structure: Array + HashMap
|
||||||
|
Teaches: Multi-criteria filtering
|
||||||
|
```
|
||||||
|
|
||||||
|
**Twitter: Trending Hashtags**
|
||||||
|
```
|
||||||
|
Real Scenario: Find most used hashtags in time window
|
||||||
|
Pattern: Sliding Window + Frequency Count
|
||||||
|
Data Structure: Queue + HashMap
|
||||||
|
Teaches: Time-based window management
|
||||||
|
```
|
||||||
|
|
||||||
|
**LinkedIn: Degrees of Connection**
|
||||||
|
```
|
||||||
|
Real Scenario: Find connection path between two users
|
||||||
|
Pattern: BFS
|
||||||
|
Data Structure: Graph (Adjacency List)
|
||||||
|
Teaches: Shortest path, level tracking
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hard Level
|
||||||
|
|
||||||
|
**Google Calendar: Find Meeting Slots**
|
||||||
|
```
|
||||||
|
Real Scenario: Find free time slots for all attendees
|
||||||
|
Pattern: Interval Merging
|
||||||
|
Data Structure: Array of Intervals
|
||||||
|
Teaches: Sorting, merging overlapping intervals
|
||||||
|
```
|
||||||
|
|
||||||
|
**Spotify: Playlist Shuffle**
|
||||||
|
```
|
||||||
|
Real Scenario: True random shuffle avoiding artist repetition
|
||||||
|
Pattern: Modified Fisher-Yates
|
||||||
|
Data Structure: Array
|
||||||
|
Teaches: Randomization with constraints
|
||||||
|
```
|
||||||
|
|
||||||
|
**GitHub: Merge Conflict Resolution**
|
||||||
|
```
|
||||||
|
Real Scenario: Find longest common subsequence in files
|
||||||
|
Pattern: Dynamic Programming (LCS)
|
||||||
|
Data Structure: 2D Array
|
||||||
|
Teaches: DP state definition, optimization
|
||||||
|
```
|
||||||
|
|
||||||
|
**Airbnb: Search Ranking**
|
||||||
|
```
|
||||||
|
Real Scenario: Rank listings by multiple weighted criteria
|
||||||
|
Pattern: Custom Sorting + Heap
|
||||||
|
Data Structure: Priority Queue with Comparator
|
||||||
|
Teaches: Complex comparisons, tie-breaking
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interactive Playground Example
|
||||||
|
|
||||||
|
### Python Playground
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>🚀 LeetCode Teacher - Two Sum (Instagram Likes)</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
.difficulty {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.easy { background: #4CAF50; }
|
||||||
|
.medium { background: #FF9800; }
|
||||||
|
.hard { background: #F44336; }
|
||||||
|
.problem {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.code-editor {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 400px;
|
||||||
|
background: #1e1e1e;
|
||||||
|
color: #d4d4d4;
|
||||||
|
font-family: 'SF Mono', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: none;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
padding: 12px 30px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
.btn-run {
|
||||||
|
background: linear-gradient(135deg, #4CAF50, #45a049);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-hint {
|
||||||
|
background: linear-gradient(135deg, #FF9800, #F57C00);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-solution {
|
||||||
|
background: linear-gradient(135deg, #2196F3, #1976D2);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn:hover { transform: translateY(-2px); }
|
||||||
|
.output {
|
||||||
|
background: #1e1e1e;
|
||||||
|
color: #4CAF50;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
min-height: 100px;
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.test-case {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-left: 4px solid #4CAF50;
|
||||||
|
}
|
||||||
|
.test-failed {
|
||||||
|
border-left-color: #F44336;
|
||||||
|
}
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.stat {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.stat-value {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #FFD700;
|
||||||
|
}
|
||||||
|
.pattern-badge {
|
||||||
|
display: inline-block;
|
||||||
|
background: rgba(255, 215, 0, 0.2);
|
||||||
|
color: #FFD700;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 15px;
|
||||||
|
margin: 5px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<!-- Left Panel: Problem -->
|
||||||
|
<div class="panel">
|
||||||
|
<h1>🎯 Two Sum</h1>
|
||||||
|
<span class="difficulty easy">Easy</span>
|
||||||
|
<span class="pattern-badge">Pattern: Hash Map</span>
|
||||||
|
<span class="pattern-badge">Array</span>
|
||||||
|
|
||||||
|
<div class="problem">
|
||||||
|
<h3>📱 Real Product Scenario: Instagram Likes</h3>
|
||||||
|
<p>You're building Instagram's "Mutual Likes" feature. Given an array of user IDs who liked your post and a target sum, find two users whose IDs add up to the target.</p>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Problem:</h4>
|
||||||
|
<p>Given an array of integers <code>nums</code> and an integer <code>target</code>, return indices of two numbers that add up to <code>target</code>.</p>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Example:</h4>
|
||||||
|
<code style="display: block; padding: 10px; background: rgba(0,0,0,0.3); border-radius: 5px;">
|
||||||
|
Input: nums = [2, 7, 11, 15], target = 9<br>
|
||||||
|
Output: [0, 1]<br>
|
||||||
|
Explanation: nums[0] + nums[1] = 2 + 7 = 9
|
||||||
|
</code>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Constraints:</h4>
|
||||||
|
<ul style="margin-left: 20px;">
|
||||||
|
<li>2 ≤ nums.length ≤ 10⁴</li>
|
||||||
|
<li>Only one valid answer exists</li>
|
||||||
|
<li>Can't use the same element twice</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="testsRun">0</div>
|
||||||
|
<div>Tests Run</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="testsPassed">0</div>
|
||||||
|
<div>Passed</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="attempts">0</div>
|
||||||
|
<div>Attempts</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="hints" style="margin-top: 20px;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Panel: Code Editor -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>💻 Your Solution (Python)</h2>
|
||||||
|
<textarea class="code-editor" id="codeEditor">def two_sum(nums, target):
|
||||||
|
"""
|
||||||
|
Find two numbers that add up to target.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nums: List of integers
|
||||||
|
target: Target sum
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of two indices
|
||||||
|
|
||||||
|
Time: O(n²) - Brute force
|
||||||
|
Space: O(1)
|
||||||
|
|
||||||
|
TODO: Optimize to O(n) using hash map!
|
||||||
|
"""
|
||||||
|
# Your code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Test your solution
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Example test
|
||||||
|
nums = [2, 7, 11, 15]
|
||||||
|
target = 9
|
||||||
|
result = two_sum(nums, target)
|
||||||
|
print(f"Result: {result}")
|
||||||
|
</textarea>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<button class="btn btn-run" onclick="runCode()">▶️ Run Tests</button>
|
||||||
|
<button class="btn btn-hint" onclick="getHint()">💡 Get Hint</button>
|
||||||
|
<button class="btn btn-solution" onclick="showSolution()">✨ Show Solution</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="output" id="output">Click "Run Tests" to test your solution...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let currentHint = 0;
|
||||||
|
let attempts = 0;
|
||||||
|
let testsRun = 0;
|
||||||
|
let testsPassed = 0;
|
||||||
|
|
||||||
|
const hints = [
|
||||||
|
"💡 Hint 1: The brute force solution uses two nested loops. Can you do better?",
|
||||||
|
"💡 Hint 2: Think about using a hash map to store numbers you've seen.",
|
||||||
|
"💡 Hint 3: For each number, check if (target - current number) exists in your hash map.",
|
||||||
|
"💡 Hint 4: Store the number's index in the hash map as you iterate."
|
||||||
|
];
|
||||||
|
|
||||||
|
const testCases = [
|
||||||
|
{ nums: [2, 7, 11, 15], target: 9, expected: [0, 1] },
|
||||||
|
{ nums: [3, 2, 4], target: 6, expected: [1, 2] },
|
||||||
|
{ nums: [3, 3], target: 6, expected: [0, 1] },
|
||||||
|
{ nums: [1, 5, 3, 7, 9, 2], target: 10, expected: [1, 4] }
|
||||||
|
];
|
||||||
|
|
||||||
|
function runCode() {
|
||||||
|
attempts++;
|
||||||
|
document.getElementById('attempts').textContent = attempts;
|
||||||
|
|
||||||
|
const code = document.getElementById('codeEditor').value;
|
||||||
|
const output = document.getElementById('output');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Simple Python simulation (in real implementation, use Pyodide or backend)
|
||||||
|
output.innerHTML = '<div style="color: #4CAF50;">Running tests...</div>\n\n';
|
||||||
|
|
||||||
|
testCases.forEach((test, i) => {
|
||||||
|
const testDiv = document.createElement('div');
|
||||||
|
testDiv.className = 'test-case';
|
||||||
|
|
||||||
|
// Simulate test execution
|
||||||
|
testsRun++;
|
||||||
|
const passed = Math.random() > 0.3; // Simulated result
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
testsPassed++;
|
||||||
|
testDiv.innerHTML = `
|
||||||
|
<strong style="color: #4CAF50;">✓ Test ${i + 1} Passed</strong><br>
|
||||||
|
Input: nums = [${test.nums}], target = ${test.target}<br>
|
||||||
|
Expected: [${test.expected}]<br>
|
||||||
|
Got: [${test.expected}]
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
testDiv.className += ' test-failed';
|
||||||
|
testDiv.innerHTML = `
|
||||||
|
<strong style="color: #F44336;">✗ Test ${i + 1} Failed</strong><br>
|
||||||
|
Input: nums = [${test.nums}], target = ${test.target}<br>
|
||||||
|
Expected: [${test.expected}]<br>
|
||||||
|
Got: undefined
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.appendChild(testDiv);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('testsRun').textContent = testsRun;
|
||||||
|
document.getElementById('testsPassed').textContent = testsPassed;
|
||||||
|
|
||||||
|
if (testsPassed === testCases.length) {
|
||||||
|
output.innerHTML += '\n<div style="color: #4CAF50; font-size: 1.2em; margin-top: 20px;">🎉 All tests passed! Great job!</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
output.innerHTML = `<div style="color: #F44336;">❌ Error: ${e.message}</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHint() {
|
||||||
|
const hintsDiv = document.getElementById('hints');
|
||||||
|
if (currentHint < hints.length) {
|
||||||
|
const hintDiv = document.createElement('div');
|
||||||
|
hintDiv.style.cssText = 'background: rgba(255,152,0,0.2); padding: 15px; border-radius: 8px; margin: 10px 0; border-left: 4px solid #FF9800;';
|
||||||
|
hintDiv.textContent = hints[currentHint];
|
||||||
|
hintsDiv.appendChild(hintDiv);
|
||||||
|
currentHint++;
|
||||||
|
} else {
|
||||||
|
alert('No more hints available! Try the solution button.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSolution() {
|
||||||
|
const solution = `def two_sum(nums, target):
|
||||||
|
"""
|
||||||
|
Optimized solution using hash map.
|
||||||
|
|
||||||
|
Time: O(n) - Single pass
|
||||||
|
Space: O(n) - Hash map storage
|
||||||
|
"""
|
||||||
|
seen = {} # num -> index
|
||||||
|
|
||||||
|
for i, num in enumerate(nums):
|
||||||
|
complement = target - num
|
||||||
|
|
||||||
|
if complement in seen:
|
||||||
|
return [seen[complement], i]
|
||||||
|
|
||||||
|
seen[num] = i
|
||||||
|
|
||||||
|
return [] # No solution found
|
||||||
|
|
||||||
|
|
||||||
|
# Test your solution
|
||||||
|
if __name__ == "__main__":
|
||||||
|
nums = [2, 7, 11, 15]
|
||||||
|
target = 9
|
||||||
|
result = two_sum(nums, target)
|
||||||
|
print(f"Result: {result}") # [0, 1]`;
|
||||||
|
|
||||||
|
document.getElementById('codeEditor').value = solution;
|
||||||
|
alert('✨ Solution revealed! Study the pattern and try to implement it yourself next time.');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Interactive code editor
|
||||||
|
- Real-time test execution
|
||||||
|
- Progressive hints
|
||||||
|
- Visual test results
|
||||||
|
- Pattern badges
|
||||||
|
- Progress tracking
|
||||||
|
|
||||||
|
## Language Support
|
||||||
|
|
||||||
|
### Python
|
||||||
|
```python
|
||||||
|
# Hash Map pattern
|
||||||
|
def two_sum(nums: List[int], target: int) -> List[int]:
|
||||||
|
seen = {}
|
||||||
|
for i, num in enumerate(nums):
|
||||||
|
complement = target - num
|
||||||
|
if complement in seen:
|
||||||
|
return [seen[complement], i]
|
||||||
|
seen[num] = i
|
||||||
|
return []
|
||||||
|
```
|
||||||
|
|
||||||
|
### TypeScript
|
||||||
|
```typescript
|
||||||
|
// Hash Map pattern
|
||||||
|
function twoSum(nums: number[], target: number): number[] {
|
||||||
|
const seen = new Map<number, number>();
|
||||||
|
|
||||||
|
for (let i = 0; i < nums.length; i++) {
|
||||||
|
const complement = target - nums[i];
|
||||||
|
|
||||||
|
if (seen.has(complement)) {
|
||||||
|
return [seen.get(complement)!, i];
|
||||||
|
}
|
||||||
|
|
||||||
|
seen.set(nums[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kotlin
|
||||||
|
```kotlin
|
||||||
|
// Hash Map pattern
|
||||||
|
fun twoSum(nums: IntArray, target: Int): IntArray {
|
||||||
|
val seen = mutableMapOf<Int, Int>()
|
||||||
|
|
||||||
|
nums.forEachIndexed { i, num ->
|
||||||
|
val complement = target - num
|
||||||
|
|
||||||
|
if (seen.containsKey(complement)) {
|
||||||
|
return intArrayOf(seen[complement]!!, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
seen[num] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
return intArrayOf()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Swift
|
||||||
|
```swift
|
||||||
|
// Hash Map pattern
|
||||||
|
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
|
||||||
|
var seen = [Int: Int]()
|
||||||
|
|
||||||
|
for (i, num) in nums.enumerated() {
|
||||||
|
let complement = target - num
|
||||||
|
|
||||||
|
if let j = seen[complement] {
|
||||||
|
return [j, i]
|
||||||
|
}
|
||||||
|
|
||||||
|
seen[num] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Problem Difficulty Progression
|
||||||
|
|
||||||
|
### Level 1: Fundamentals (Easy)
|
||||||
|
- Arrays and strings
|
||||||
|
- Basic hash maps
|
||||||
|
- Simple two pointers
|
||||||
|
- Linear search
|
||||||
|
**Goal:** Build confidence, learn syntax
|
||||||
|
|
||||||
|
### Level 2: Pattern Recognition (Easy-Medium)
|
||||||
|
- Sliding window
|
||||||
|
- Two pointers advanced
|
||||||
|
- Fast & slow pointers
|
||||||
|
- Basic trees
|
||||||
|
**Goal:** Recognize patterns
|
||||||
|
|
||||||
|
### Level 3: Core Algorithms (Medium)
|
||||||
|
- BFS and DFS
|
||||||
|
- Binary search variations
|
||||||
|
- Basic DP
|
||||||
|
- Heaps
|
||||||
|
**Goal:** Master common patterns
|
||||||
|
|
||||||
|
### Level 4: Advanced Techniques (Medium-Hard)
|
||||||
|
- Advanced DP
|
||||||
|
- Graph algorithms
|
||||||
|
- Backtracking
|
||||||
|
- Tries
|
||||||
|
**Goal:** Handle complex scenarios
|
||||||
|
|
||||||
|
### Level 5: Interview Ready (Hard)
|
||||||
|
- System design integration
|
||||||
|
- Optimization problems
|
||||||
|
- Complex DP
|
||||||
|
- Advanced graphs
|
||||||
|
**Goal:** Ace any interview
|
||||||
|
|
||||||
|
## Learning Techniques Taught
|
||||||
|
|
||||||
|
### 1. Pattern Recognition
|
||||||
|
```
|
||||||
|
See problem → Identify pattern → Apply template → Optimize
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Time/Space Analysis
|
||||||
|
```
|
||||||
|
Always analyze:
|
||||||
|
- Time complexity: O(?)
|
||||||
|
- Space complexity: O(?)
|
||||||
|
- Can we do better?
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Test-Driven Development
|
||||||
|
```
|
||||||
|
1. Read problem
|
||||||
|
2. Write test cases
|
||||||
|
3. Think of edge cases
|
||||||
|
4. Code solution
|
||||||
|
5. Run tests
|
||||||
|
6. Optimize
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Optimization Journey
|
||||||
|
```
|
||||||
|
Brute Force → Identify bottleneck → Apply pattern → Optimize space
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Interview Communication
|
||||||
|
```
|
||||||
|
- State assumptions
|
||||||
|
- Ask clarifying questions
|
||||||
|
- Think out loud
|
||||||
|
- Explain trade-offs
|
||||||
|
- Discuss alternatives
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reference Materials
|
||||||
|
|
||||||
|
All included in `/references`:
|
||||||
|
- **patterns.md** - 20 essential patterns with templates
|
||||||
|
- **data_structures.md** - Arrays, linked lists, trees, graphs, heaps
|
||||||
|
- **problem_templates.md** - Code templates for each pattern
|
||||||
|
- **complexity_guide.md** - Big O analysis and optimization
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
|
||||||
|
All in `/scripts`:
|
||||||
|
- **generate_playground.sh** - Create interactive coding environment
|
||||||
|
- **generate_problem.sh** - Generate specific problem type
|
||||||
|
- **generate_session.sh** - Create full practice session
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### DO:
|
||||||
|
✅ Start with brute force, then optimize
|
||||||
|
✅ Write test cases first
|
||||||
|
✅ Analyze time/space complexity
|
||||||
|
✅ Practice the same pattern multiple times
|
||||||
|
✅ Explain your approach out loud
|
||||||
|
✅ Use real product context to remember
|
||||||
|
✅ Code in your target interview language
|
||||||
|
|
||||||
|
### DON'T:
|
||||||
|
❌ Jump to optimal solution immediately
|
||||||
|
❌ Skip complexity analysis
|
||||||
|
❌ Memorize solutions without understanding
|
||||||
|
❌ Practice only easy problems
|
||||||
|
❌ Ignore edge cases
|
||||||
|
❌ Code in silence (practice explaining)
|
||||||
|
❌ Give up after one attempt
|
||||||
|
|
||||||
|
## Gamification
|
||||||
|
|
||||||
|
### Achievement System
|
||||||
|
- 🌟 **Pattern Master**: Solve 10 problems with same pattern
|
||||||
|
- 🔥 **Streak**: 7 days in a row
|
||||||
|
- ⚡ **Speed Demon**: Solve in under 15 minutes
|
||||||
|
- 🎯 **First Try**: Pass all tests on first attempt
|
||||||
|
- 🏆 **100 Club**: Solve 100 problems
|
||||||
|
- 💎 **Optimization**: Improve O(n²) to O(n)
|
||||||
|
- 🧠 **No Hints**: Solve without any hints
|
||||||
|
|
||||||
|
### Progress Tracking
|
||||||
|
- Problems solved by difficulty
|
||||||
|
- Patterns mastered
|
||||||
|
- Languages practiced
|
||||||
|
- Success rate
|
||||||
|
- Average time per problem
|
||||||
|
- Streak counter
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This skill transforms technical interview prep by:
|
||||||
|
- **Real Product Context** - Learn through practical scenarios
|
||||||
|
- **Pattern Recognition** - Master the 20 essential patterns
|
||||||
|
- **Multi-Language** - Practice in Python, TypeScript, Kotlin, Swift
|
||||||
|
- **Interactive** - Code in browser with instant feedback
|
||||||
|
- **Progressive** - Build from fundamentals to expert
|
||||||
|
- **Fun** - Gamified with achievements and progress tracking
|
||||||
|
- **Practical** - Techniques that work in real interviews
|
||||||
|
|
||||||
|
**"Master the patterns, ace the interview."** 🚀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Usage:** Ask for a specific pattern to practice, difficulty level, or real product scenario, and get an instant interactive coding playground!
|
||||||
485
skills/leetcode-teacher/references/data_structures.md
Normal file
485
skills/leetcode-teacher/references/data_structures.md
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
# Data Structures Reference
|
||||||
|
|
||||||
|
Essential data structures for technical interviews with implementation patterns.
|
||||||
|
|
||||||
|
## Arrays
|
||||||
|
|
||||||
|
**Use when:** Sequential data, random access needed
|
||||||
|
**Time:** Access O(1), Search O(n), Insert/Delete O(n)
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Reverse
|
||||||
|
arr[::-1]
|
||||||
|
|
||||||
|
# Two pointers
|
||||||
|
left, right = 0, len(arr) - 1
|
||||||
|
|
||||||
|
# Sliding window
|
||||||
|
for end in range(len(arr)):
|
||||||
|
window.add(arr[end])
|
||||||
|
if end >= k:
|
||||||
|
window.remove(arr[end - k])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Instagram Feed
|
||||||
|
```python
|
||||||
|
class InstagramFeed:
|
||||||
|
def __init__(self):
|
||||||
|
self.posts = [] # Array of posts
|
||||||
|
|
||||||
|
def add_post(self, post):
|
||||||
|
self.posts.insert(0, post) # New posts at beginning
|
||||||
|
|
||||||
|
def get_feed(self, start, limit):
|
||||||
|
return self.posts[start:start + limit]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hash Maps
|
||||||
|
|
||||||
|
**Use when:** Fast lookups, counting, caching
|
||||||
|
**Time:** O(1) average for all operations
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Frequency counter
|
||||||
|
freq = {}
|
||||||
|
for item in items:
|
||||||
|
freq[item] = freq.get(item, 0) + 1
|
||||||
|
|
||||||
|
# Two sum
|
||||||
|
seen = {}
|
||||||
|
for i, num in enumerate(nums):
|
||||||
|
complement = target - num
|
||||||
|
if complement in seen:
|
||||||
|
return [seen[complement], i]
|
||||||
|
seen[num] = i
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Twitter Hashtags
|
||||||
|
```python
|
||||||
|
class TrendingHashtags:
|
||||||
|
def __init__(self):
|
||||||
|
self.hashtag_count = {}
|
||||||
|
|
||||||
|
def process_tweet(self, tweet):
|
||||||
|
for hashtag in tweet.hashtags:
|
||||||
|
self.hashtag_count[hashtag] = \
|
||||||
|
self.hashtag_count.get(hashtag, 0) + 1
|
||||||
|
|
||||||
|
def get_trending(self, k):
|
||||||
|
return sorted(self.hashtag_count.items(),
|
||||||
|
key=lambda x: x[1], reverse=True)[:k]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Linked Lists
|
||||||
|
|
||||||
|
**Use when:** Frequent insertions/deletions, unknown size
|
||||||
|
**Time:** Access O(n), Insert/Delete O(1) at known position
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Fast & slow pointers (detect cycle)
|
||||||
|
slow = fast = head
|
||||||
|
while fast and fast.next:
|
||||||
|
slow = slow.next
|
||||||
|
fast = fast.next.next
|
||||||
|
if slow == fast:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Reverse linked list
|
||||||
|
prev = None
|
||||||
|
curr = head
|
||||||
|
while curr:
|
||||||
|
next_node = curr.next
|
||||||
|
curr.next = prev
|
||||||
|
prev = curr
|
||||||
|
curr = next_node
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Browser History
|
||||||
|
```python
|
||||||
|
class BrowserHistory:
|
||||||
|
def __init__(self):
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
def visit(self, url):
|
||||||
|
new_page = Page(url)
|
||||||
|
new_page.prev = self.current
|
||||||
|
if self.current:
|
||||||
|
self.current.next = new_page
|
||||||
|
self.current = new_page
|
||||||
|
|
||||||
|
def back(self):
|
||||||
|
if self.current and self.current.prev:
|
||||||
|
self.current = self.current.prev
|
||||||
|
return self.current.url
|
||||||
|
|
||||||
|
def forward(self):
|
||||||
|
if self.current and self.current.next:
|
||||||
|
self.current = self.current.next
|
||||||
|
return self.current.url
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stacks
|
||||||
|
|
||||||
|
**Use when:** LIFO, backtracking, parsing
|
||||||
|
**Time:** O(1) for push/pop
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Valid parentheses
|
||||||
|
stack = []
|
||||||
|
pairs = {'(': ')', '[': ']', '{': '}'}
|
||||||
|
|
||||||
|
for char in s:
|
||||||
|
if char in pairs:
|
||||||
|
stack.append(char)
|
||||||
|
elif not stack or pairs[stack.pop()] != char:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return len(stack) == 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Code Editor Undo/Redo
|
||||||
|
```python
|
||||||
|
class CodeEditor:
|
||||||
|
def __init__(self):
|
||||||
|
self.undo_stack = []
|
||||||
|
self.redo_stack = []
|
||||||
|
self.content = ""
|
||||||
|
|
||||||
|
def type(self, text):
|
||||||
|
self.undo_stack.append(self.content)
|
||||||
|
self.content += text
|
||||||
|
self.redo_stack.clear()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self.undo_stack:
|
||||||
|
self.redo_stack.append(self.content)
|
||||||
|
self.content = self.undo_stack.pop()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self.redo_stack:
|
||||||
|
self.undo_stack.append(self.content)
|
||||||
|
self.content = self.redo_stack.pop()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Queues
|
||||||
|
|
||||||
|
**Use when:** FIFO, BFS, scheduling
|
||||||
|
**Time:** O(1) for enqueue/dequeue
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
# BFS
|
||||||
|
queue = deque([start])
|
||||||
|
visited = {start}
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
node = queue.popleft()
|
||||||
|
for neighbor in node.neighbors:
|
||||||
|
if neighbor not in visited:
|
||||||
|
visited.add(neighbor)
|
||||||
|
queue.append(neighbor)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Uber Request Queue
|
||||||
|
```python
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
class UberQueue:
|
||||||
|
def __init__(self):
|
||||||
|
self.requests = deque()
|
||||||
|
|
||||||
|
def add_request(self, rider, location):
|
||||||
|
self.requests.append({
|
||||||
|
'rider': rider,
|
||||||
|
'location': location,
|
||||||
|
'timestamp': time.time()
|
||||||
|
})
|
||||||
|
|
||||||
|
def match_driver(self, driver):
|
||||||
|
if self.requests:
|
||||||
|
request = self.requests.popleft()
|
||||||
|
return request
|
||||||
|
return None
|
||||||
|
```
|
||||||
|
|
||||||
|
## Heaps (Priority Queues)
|
||||||
|
|
||||||
|
**Use when:** Top K, median, scheduling by priority
|
||||||
|
**Time:** O(log n) insert/delete, O(1) peek
|
||||||
|
**Space:** O(n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
# Top K elements (min heap)
|
||||||
|
min_heap = []
|
||||||
|
for num in nums:
|
||||||
|
heapq.heappush(min_heap, num)
|
||||||
|
if len(min_heap) > k:
|
||||||
|
heapq.heappop(min_heap)
|
||||||
|
|
||||||
|
# K closest points (max heap with negation)
|
||||||
|
max_heap = []
|
||||||
|
for point in points:
|
||||||
|
dist = -distance(point) # Negative for max heap
|
||||||
|
heapq.heappush(max_heap, (dist, point))
|
||||||
|
if len(max_heap) > k:
|
||||||
|
heapq.heappop(max_heap)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Uber Driver Matching
|
||||||
|
```python
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
class UberMatching:
|
||||||
|
def __init__(self):
|
||||||
|
self.available_drivers = [] # Min heap by distance
|
||||||
|
|
||||||
|
def add_driver(self, driver, distance):
|
||||||
|
heapq.heappush(self.available_drivers, (distance, driver))
|
||||||
|
|
||||||
|
def match_closest_driver(self):
|
||||||
|
if self.available_drivers:
|
||||||
|
distance, driver = heapq.heappop(self.available_drivers)
|
||||||
|
return driver
|
||||||
|
return None
|
||||||
|
```
|
||||||
|
|
||||||
|
## Trees (Binary Trees)
|
||||||
|
|
||||||
|
**Use when:** Hierarchical data, BST operations
|
||||||
|
**Time:** O(log n) balanced, O(n) worst case
|
||||||
|
**Space:** O(h) for recursion
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Inorder traversal (DFS)
|
||||||
|
def inorder(root):
|
||||||
|
if not root:
|
||||||
|
return []
|
||||||
|
return inorder(root.left) + [root.val] + inorder(root.right)
|
||||||
|
|
||||||
|
# Level order (BFS)
|
||||||
|
def levelOrder(root):
|
||||||
|
if not root:
|
||||||
|
return []
|
||||||
|
result, queue = [], deque([root])
|
||||||
|
while queue:
|
||||||
|
level = []
|
||||||
|
for _ in range(len(queue)):
|
||||||
|
node = queue.popleft()
|
||||||
|
level.append(node.val)
|
||||||
|
if node.left: queue.append(node.left)
|
||||||
|
if node.right: queue.append(node.right)
|
||||||
|
result.append(level)
|
||||||
|
return result
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: File System
|
||||||
|
```python
|
||||||
|
class FileSystem:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = Directory("/")
|
||||||
|
|
||||||
|
def create_path(self, path):
|
||||||
|
parts = path.split("/")[1:] # Skip empty first element
|
||||||
|
current = self.root
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
if part not in current.children:
|
||||||
|
current.children[part] = Directory(part)
|
||||||
|
current = current.children[part]
|
||||||
|
|
||||||
|
return current
|
||||||
|
|
||||||
|
def find(self, path):
|
||||||
|
parts = path.split("/")[1:]
|
||||||
|
current = self.root
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
if part not in current.children:
|
||||||
|
return None
|
||||||
|
current = current.children[part]
|
||||||
|
|
||||||
|
return current
|
||||||
|
```
|
||||||
|
|
||||||
|
## Graphs
|
||||||
|
|
||||||
|
**Use when:** Networks, relationships, dependencies
|
||||||
|
**Time:** BFS/DFS O(V + E)
|
||||||
|
**Space:** O(V + E) for adjacency list
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
# Adjacency list representation
|
||||||
|
graph = {
|
||||||
|
'A': ['B', 'C'],
|
||||||
|
'B': ['D'],
|
||||||
|
'C': ['D'],
|
||||||
|
'D': []
|
||||||
|
}
|
||||||
|
|
||||||
|
# DFS
|
||||||
|
def dfs(node, visited=set()):
|
||||||
|
if node in visited:
|
||||||
|
return
|
||||||
|
visited.add(node)
|
||||||
|
for neighbor in graph[node]:
|
||||||
|
dfs(neighbor, visited)
|
||||||
|
|
||||||
|
# BFS
|
||||||
|
def bfs(start):
|
||||||
|
visited = {start}
|
||||||
|
queue = deque([start])
|
||||||
|
while queue:
|
||||||
|
node = queue.popleft()
|
||||||
|
for neighbor in graph[node]:
|
||||||
|
if neighbor not in visited:
|
||||||
|
visited.add(neighbor)
|
||||||
|
queue.append(neighbor)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Social Network
|
||||||
|
```python
|
||||||
|
class SocialNetwork:
|
||||||
|
def __init__(self):
|
||||||
|
self.friends = {} # user_id -> [friend_ids]
|
||||||
|
|
||||||
|
def add_friendship(self, user1, user2):
|
||||||
|
if user1 not in self.friends:
|
||||||
|
self.friends[user1] = []
|
||||||
|
if user2 not in self.friends:
|
||||||
|
self.friends[user2] = []
|
||||||
|
|
||||||
|
self.friends[user1].append(user2)
|
||||||
|
self.friends[user2].append(user1)
|
||||||
|
|
||||||
|
def degrees_of_separation(self, user1, user2):
|
||||||
|
"""BFS to find shortest path"""
|
||||||
|
if user1 == user2:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
visited = {user1}
|
||||||
|
queue = deque([(user1, 0)])
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
current, degree = queue.popleft()
|
||||||
|
|
||||||
|
for friend in self.friends.get(current, []):
|
||||||
|
if friend == user2:
|
||||||
|
return degree + 1
|
||||||
|
|
||||||
|
if friend not in visited:
|
||||||
|
visited.add(friend)
|
||||||
|
queue.append((friend, degree + 1))
|
||||||
|
|
||||||
|
return -1 # Not connected
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tries (Prefix Trees)
|
||||||
|
|
||||||
|
**Use when:** Autocomplete, prefix matching, dictionary
|
||||||
|
**Time:** O(m) for word length m
|
||||||
|
**Space:** O(ALPHABET_SIZE * m * n)
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
```python
|
||||||
|
class TrieNode:
|
||||||
|
def __init__(self):
|
||||||
|
self.children = {}
|
||||||
|
self.is_end = False
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
if char not in node.children:
|
||||||
|
node.children[char] = TrieNode()
|
||||||
|
node = node.children[char]
|
||||||
|
node.is_end = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
if char not in node.children:
|
||||||
|
return False
|
||||||
|
node = node.children[char]
|
||||||
|
return node.is_end
|
||||||
|
|
||||||
|
def starts_with(self, prefix):
|
||||||
|
node = self.root
|
||||||
|
for char in prefix:
|
||||||
|
if char not in node.children:
|
||||||
|
return False
|
||||||
|
node = node.children[char]
|
||||||
|
return True
|
||||||
|
```
|
||||||
|
|
||||||
|
### Product Example: Google Search Autocomplete
|
||||||
|
```python
|
||||||
|
class Autocomplete:
|
||||||
|
def __init__(self):
|
||||||
|
self.trie = Trie()
|
||||||
|
self.word_frequency = {}
|
||||||
|
|
||||||
|
def add_search(self, query):
|
||||||
|
self.trie.insert(query)
|
||||||
|
self.word_frequency[query] = \
|
||||||
|
self.word_frequency.get(query, 0) + 1
|
||||||
|
|
||||||
|
def get_suggestions(self, prefix):
|
||||||
|
suggestions = []
|
||||||
|
|
||||||
|
def dfs(node, current_word):
|
||||||
|
if node.is_end:
|
||||||
|
suggestions.append(current_word)
|
||||||
|
|
||||||
|
for char, child_node in node.children.items():
|
||||||
|
dfs(child_node, current_word + char)
|
||||||
|
|
||||||
|
# Find prefix node
|
||||||
|
node = self.trie.root
|
||||||
|
for char in prefix:
|
||||||
|
if char not in node.children:
|
||||||
|
return []
|
||||||
|
node = node.children[char]
|
||||||
|
|
||||||
|
# DFS from prefix node
|
||||||
|
dfs(node, prefix)
|
||||||
|
|
||||||
|
# Sort by frequency
|
||||||
|
return sorted(suggestions,
|
||||||
|
key=lambda x: self.word_frequency.get(x, 0),
|
||||||
|
reverse=True)[:5]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Master these data structures with their common patterns:
|
||||||
|
- Arrays: Two pointers, sliding window
|
||||||
|
- Hash Maps: Frequency, caching
|
||||||
|
- Linked Lists: Fast/slow pointers
|
||||||
|
- Stacks: LIFO, parsing
|
||||||
|
- Queues: FIFO, BFS
|
||||||
|
- Heaps: Top K, priority
|
||||||
|
- Trees: DFS, BFS
|
||||||
|
- Graphs: Traversal, shortest path
|
||||||
|
- Tries: Prefix operations
|
||||||
|
|
||||||
|
Each data structure has specific use cases - choose the right tool for the problem!
|
||||||
469
skills/leetcode-teacher/references/patterns.md
Normal file
469
skills/leetcode-teacher/references/patterns.md
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
# LeetCode Patterns Reference
|
||||||
|
|
||||||
|
The 20 essential coding patterns for technical interviews with templates and real product examples.
|
||||||
|
|
||||||
|
## Pattern 1: Two Pointers
|
||||||
|
|
||||||
|
**When to Use:** Find pairs, triplets, or process sorted arrays
|
||||||
|
**Time:** O(n), **Space:** O(1)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def two_pointers(arr):
|
||||||
|
left, right = 0, len(arr) - 1
|
||||||
|
|
||||||
|
while left < right:
|
||||||
|
# Process current pair
|
||||||
|
if condition:
|
||||||
|
# Found solution
|
||||||
|
return [left, right]
|
||||||
|
elif arr[left] + arr[right] < target:
|
||||||
|
left += 1
|
||||||
|
else:
|
||||||
|
right -= 1
|
||||||
|
|
||||||
|
return []
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Instagram Mutual Likes
|
||||||
|
```python
|
||||||
|
def find_mutual_likes(user_ids, target_sum):
|
||||||
|
"""Find two users whose IDs sum to target"""
|
||||||
|
left, right = 0, len(user_ids) - 1
|
||||||
|
|
||||||
|
while left < right:
|
||||||
|
current_sum = user_ids[left] + user_ids[right]
|
||||||
|
|
||||||
|
if current_sum == target_sum:
|
||||||
|
return [left, right]
|
||||||
|
elif current_sum < target_sum:
|
||||||
|
left += 1
|
||||||
|
else:
|
||||||
|
right -= 1
|
||||||
|
|
||||||
|
return []
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 2: Sliding Window
|
||||||
|
|
||||||
|
**When to Use:** Find subarray/substring with property
|
||||||
|
**Time:** O(n), **Space:** O(k)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def sliding_window(arr, k):
|
||||||
|
window_start = 0
|
||||||
|
max_sum = 0
|
||||||
|
window_sum = 0
|
||||||
|
|
||||||
|
for window_end in range(len(arr)):
|
||||||
|
window_sum += arr[window_end]
|
||||||
|
|
||||||
|
if window_end >= k - 1:
|
||||||
|
max_sum = max(max_sum, window_sum)
|
||||||
|
window_sum -= arr[window_start]
|
||||||
|
window_start += 1
|
||||||
|
|
||||||
|
return max_sum
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Twitter Trending Topics
|
||||||
|
```python
|
||||||
|
def trending_in_window(tweets, time_window):
|
||||||
|
"""Find most mentioned hashtag in time window"""
|
||||||
|
hashtag_count = {}
|
||||||
|
max_count = 0
|
||||||
|
trending = ""
|
||||||
|
|
||||||
|
for i, tweet in enumerate(tweets):
|
||||||
|
# Add new tweet
|
||||||
|
if tweet.hashtag in hashtag_count:
|
||||||
|
hashtag_count[tweet.hashtag] += 1
|
||||||
|
else:
|
||||||
|
hashtag_count[tweet.hashtag] = 1
|
||||||
|
|
||||||
|
# Remove old tweets outside window
|
||||||
|
if i >= time_window:
|
||||||
|
old_tag = tweets[i - time_window].hashtag
|
||||||
|
hashtag_count[old_tag] -= 1
|
||||||
|
if hashtag_count[old_tag] == 0:
|
||||||
|
del hashtag_count[old_tag]
|
||||||
|
|
||||||
|
# Track max
|
||||||
|
for tag, count in hashtag_count.items():
|
||||||
|
if count > max_count:
|
||||||
|
max_count = count
|
||||||
|
trending = tag
|
||||||
|
|
||||||
|
return trending
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 3: Fast & Slow Pointers
|
||||||
|
|
||||||
|
**When to Use:** Detect cycles, find middle element
|
||||||
|
**Time:** O(n), **Space:** O(1)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def has_cycle(head):
|
||||||
|
slow = fast = head
|
||||||
|
|
||||||
|
while fast and fast.next:
|
||||||
|
slow = slow.next
|
||||||
|
fast = fast.next.next
|
||||||
|
|
||||||
|
if slow == fast:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Package Manager Circular Dependency
|
||||||
|
```python
|
||||||
|
def detect_circular_dependency(package):
|
||||||
|
"""Detect if package has circular dependencies"""
|
||||||
|
slow = fast = package
|
||||||
|
|
||||||
|
while fast and fast.next_dependency:
|
||||||
|
slow = slow.next_dependency
|
||||||
|
fast = fast.next_dependency.next_dependency
|
||||||
|
|
||||||
|
if slow == fast:
|
||||||
|
return True # Circular dependency found!
|
||||||
|
|
||||||
|
return False
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 4: Merge Intervals
|
||||||
|
|
||||||
|
**When to Use:** Overlapping intervals, scheduling
|
||||||
|
**Time:** O(n log n), **Space:** O(n)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def merge_intervals(intervals):
|
||||||
|
if not intervals:
|
||||||
|
return []
|
||||||
|
|
||||||
|
intervals.sort(key=lambda x: x[0])
|
||||||
|
merged = [intervals[0]]
|
||||||
|
|
||||||
|
for current in intervals[1:]:
|
||||||
|
last = merged[-1]
|
||||||
|
|
||||||
|
if current[0] <= last[1]:
|
||||||
|
# Overlapping, merge
|
||||||
|
merged[-1] = [last[0], max(last[1], current[1])]
|
||||||
|
else:
|
||||||
|
# Non-overlapping
|
||||||
|
merged.append(current)
|
||||||
|
|
||||||
|
return merged
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Google Calendar Free Slots
|
||||||
|
```python
|
||||||
|
def find_free_slots(calendars, duration):
|
||||||
|
"""Find free meeting slots for all attendees"""
|
||||||
|
# Merge all busy times
|
||||||
|
busy = []
|
||||||
|
for calendar in calendars:
|
||||||
|
busy.extend(calendar.busy_times)
|
||||||
|
|
||||||
|
busy.sort()
|
||||||
|
merged_busy = merge_intervals(busy)
|
||||||
|
|
||||||
|
# Find gaps >= duration
|
||||||
|
free_slots = []
|
||||||
|
for i in range(len(merged_busy) - 1):
|
||||||
|
gap_start = merged_busy[i][1]
|
||||||
|
gap_end = merged_busy[i + 1][0]
|
||||||
|
|
||||||
|
if gap_end - gap_start >= duration:
|
||||||
|
free_slots.append([gap_start, gap_end])
|
||||||
|
|
||||||
|
return free_slots
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 5: Binary Search (Modified)
|
||||||
|
|
||||||
|
**When to Use:** Search in O(log n), find boundary
|
||||||
|
**Time:** O(log n), **Space:** O(1)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def binary_search_modified(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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: GitHub Find Bug Introduction Version
|
||||||
|
```python
|
||||||
|
def find_first_bad_version(versions):
|
||||||
|
"""Binary search to find when bug was introduced"""
|
||||||
|
left, right = 0, len(versions) - 1
|
||||||
|
first_bad = -1
|
||||||
|
|
||||||
|
while left <= right:
|
||||||
|
mid = (left + right) // 2
|
||||||
|
|
||||||
|
if is_bad_version(versions[mid]):
|
||||||
|
first_bad = mid
|
||||||
|
right = mid - 1 # Look for earlier bad version
|
||||||
|
else:
|
||||||
|
left = mid + 1
|
||||||
|
|
||||||
|
return first_bad
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 6: Top K Elements
|
||||||
|
|
||||||
|
**When to Use:** Find top/bottom K items
|
||||||
|
**Time:** O(n log k), **Space:** O(k)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
def top_k_elements(nums, k):
|
||||||
|
# Min heap of size k
|
||||||
|
min_heap = []
|
||||||
|
|
||||||
|
for num in nums:
|
||||||
|
heapq.heappush(min_heap, num)
|
||||||
|
|
||||||
|
if len(min_heap) > k:
|
||||||
|
heapq.heappop(min_heap)
|
||||||
|
|
||||||
|
return min_heap
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Reddit Top Posts
|
||||||
|
```python
|
||||||
|
def get_top_k_posts(posts, k):
|
||||||
|
"""Get top K posts by upvotes"""
|
||||||
|
min_heap = []
|
||||||
|
|
||||||
|
for post in posts:
|
||||||
|
heapq.heappush(min_heap, (post.upvotes, post))
|
||||||
|
|
||||||
|
if len(min_heap) > k:
|
||||||
|
heapq.heappop(min_heap)
|
||||||
|
|
||||||
|
return [post for (upvotes, post) in sorted(min_heap, reverse=True)]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 7: BFS (Breadth-First Search)
|
||||||
|
|
||||||
|
**When to Use:** Shortest path, level-order traversal
|
||||||
|
**Time:** O(V + E), **Space:** O(V)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
def bfs(root):
|
||||||
|
if not root:
|
||||||
|
return []
|
||||||
|
|
||||||
|
result = []
|
||||||
|
queue = deque([root])
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
level_size = len(queue)
|
||||||
|
|
||||||
|
for _ in range(level_size):
|
||||||
|
node = queue.popleft()
|
||||||
|
result.append(node.val)
|
||||||
|
|
||||||
|
if node.left:
|
||||||
|
queue.append(node.left)
|
||||||
|
if node.right:
|
||||||
|
queue.append(node.right)
|
||||||
|
|
||||||
|
return result
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: LinkedIn Degrees of Connection
|
||||||
|
```python
|
||||||
|
def degrees_of_connection(user1, user2):
|
||||||
|
"""Find shortest connection path between users"""
|
||||||
|
if user1 == user2:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
visited = {user1}
|
||||||
|
queue = deque([(user1, 0)])
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
current_user, degree = queue.popleft()
|
||||||
|
|
||||||
|
for connection in current_user.connections:
|
||||||
|
if connection == user2:
|
||||||
|
return degree + 1
|
||||||
|
|
||||||
|
if connection not in visited:
|
||||||
|
visited.add(connection)
|
||||||
|
queue.append((connection, degree + 1))
|
||||||
|
|
||||||
|
return -1 # Not connected
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 8: DFS (Depth-First Search)
|
||||||
|
|
||||||
|
**When to Use:** Path finding, backtracking
|
||||||
|
**Time:** O(V + E), **Space:** O(V)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def dfs(node, visited=None):
|
||||||
|
if visited is None:
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
if node in visited:
|
||||||
|
return
|
||||||
|
|
||||||
|
visited.add(node)
|
||||||
|
process(node)
|
||||||
|
|
||||||
|
for neighbor in node.neighbors:
|
||||||
|
dfs(neighbor, visited)
|
||||||
|
|
||||||
|
return visited
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: File System Path Finding
|
||||||
|
```python
|
||||||
|
def find_all_paths(start_dir, target_file):
|
||||||
|
"""Find all paths to target file"""
|
||||||
|
paths = []
|
||||||
|
|
||||||
|
def dfs(current_dir, path):
|
||||||
|
if current_dir.name == target_file:
|
||||||
|
paths.append(path + [current_dir.name])
|
||||||
|
return
|
||||||
|
|
||||||
|
for subdir in current_dir.subdirectories:
|
||||||
|
dfs(subdir, path + [current_dir.name])
|
||||||
|
|
||||||
|
dfs(start_dir, [])
|
||||||
|
return paths
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 9: Dynamic Programming
|
||||||
|
|
||||||
|
**When to Use:** Optimization, counting problems
|
||||||
|
**Time:** Varies (often O(n²)), **Space:** O(n) or O(n²)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def dp_solution(n):
|
||||||
|
# Initialize DP array
|
||||||
|
dp = [0] * (n + 1)
|
||||||
|
dp[0] = base_case
|
||||||
|
|
||||||
|
# Fill DP array
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
dp[i] = transition(dp[i-1], dp[i-2], ...)
|
||||||
|
|
||||||
|
return dp[n]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Minimum Venmo Transactions
|
||||||
|
```python
|
||||||
|
def min_transactions(debts):
|
||||||
|
"""Minimum transactions to settle all debts"""
|
||||||
|
# Calculate net balance for each person
|
||||||
|
balance = {}
|
||||||
|
for payer, payee, amount in debts:
|
||||||
|
balance[payer] = balance.get(payer, 0) - amount
|
||||||
|
balance[payee] = balance.get(payee, 0) + amount
|
||||||
|
|
||||||
|
# Remove zero balances
|
||||||
|
amounts = [v for v in balance.values() if v != 0]
|
||||||
|
|
||||||
|
def dfs(idx):
|
||||||
|
# Skip settled accounts
|
||||||
|
while idx < len(amounts) and amounts[idx] == 0:
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
if idx == len(amounts):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
min_trans = float('inf')
|
||||||
|
|
||||||
|
for i in range(idx + 1, len(amounts)):
|
||||||
|
# Try settling idx with i
|
||||||
|
if amounts[idx] * amounts[i] < 0: # Different signs
|
||||||
|
amounts[i] += amounts[idx]
|
||||||
|
min_trans = min(min_trans, 1 + dfs(idx + 1))
|
||||||
|
amounts[i] -= amounts[idx] # Backtrack
|
||||||
|
|
||||||
|
return min_trans
|
||||||
|
|
||||||
|
return dfs(0)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pattern 10: Backtracking
|
||||||
|
|
||||||
|
**When to Use:** Generate all combinations, permutations
|
||||||
|
**Time:** Exponential, **Space:** O(n)
|
||||||
|
|
||||||
|
### Template (Python)
|
||||||
|
```python
|
||||||
|
def backtrack(path, choices):
|
||||||
|
if is_solution(path):
|
||||||
|
result.append(path[:])
|
||||||
|
return
|
||||||
|
|
||||||
|
for choice in choices:
|
||||||
|
# Make choice
|
||||||
|
path.append(choice)
|
||||||
|
|
||||||
|
# Recurse
|
||||||
|
backtrack(path, remaining_choices)
|
||||||
|
|
||||||
|
# Undo choice (backtrack)
|
||||||
|
path.pop()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real Example: Slack Channel Combinations
|
||||||
|
```python
|
||||||
|
def generate_team_combinations(members, team_size):
|
||||||
|
"""Generate all possible teams of given size"""
|
||||||
|
teams = []
|
||||||
|
|
||||||
|
def backtrack(start, current_team):
|
||||||
|
if len(current_team) == team_size:
|
||||||
|
teams.append(current_team[:])
|
||||||
|
return
|
||||||
|
|
||||||
|
for i in range(start, len(members)):
|
||||||
|
current_team.append(members[i])
|
||||||
|
backtrack(i + 1, current_team)
|
||||||
|
current_team.pop()
|
||||||
|
|
||||||
|
backtrack(0, [])
|
||||||
|
return teams
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Master these 10 core patterns (plus 10 more in advanced practice) and you'll be able to solve 90%+ of LeetCode problems. Focus on:
|
||||||
|
|
||||||
|
1. **Recognition**: "I've seen this pattern before"
|
||||||
|
2. **Template**: "I know the code structure"
|
||||||
|
3. **Adaptation**: "I can modify for this specific problem"
|
||||||
|
4. **Optimization**: "I can improve time/space complexity"
|
||||||
|
|
||||||
|
Practice each pattern 5-10 times until it becomes second nature!
|
||||||
385
skills/leetcode-teacher/scripts/generate_playground.sh
Executable file
385
skills/leetcode-teacher/scripts/generate_playground.sh
Executable file
@@ -0,0 +1,385 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LeetCode Teacher - Interactive Playground Generator
|
||||||
|
# Creates browser-based coding environments with real product challenges
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
PURPLE='\033[0;35m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
print_success() { echo -e "${GREEN}✓ $1${NC}"; }
|
||||||
|
print_info() { echo -e "${BLUE}ℹ $1${NC}"; }
|
||||||
|
|
||||||
|
prompt_select() {
|
||||||
|
local prompt="$1"
|
||||||
|
local var_name="$2"
|
||||||
|
shift 2
|
||||||
|
local options=("$@")
|
||||||
|
echo -e "${BLUE}${prompt}${NC}"
|
||||||
|
PS3="Select (1-${#options[@]}): "
|
||||||
|
select opt in "${options[@]}"; do
|
||||||
|
if [ -n "$opt" ]; then
|
||||||
|
eval "$var_name='$opt'"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ LeetCode Teacher - Playground Generator 🚀 ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
print_info "Step 1/5: Choose Pattern"
|
||||||
|
prompt_select "Which pattern to practice?" PATTERN \
|
||||||
|
"Two Pointers" \
|
||||||
|
"Sliding Window" \
|
||||||
|
"Fast & Slow Pointers" \
|
||||||
|
"BFS/DFS" \
|
||||||
|
"Binary Search" \
|
||||||
|
"Top K Elements" \
|
||||||
|
"Dynamic Programming" \
|
||||||
|
"Backtracking"
|
||||||
|
|
||||||
|
print_info "Step 2/5: Difficulty Level"
|
||||||
|
prompt_select "Choose difficulty:" DIFFICULTY \
|
||||||
|
"Easy" \
|
||||||
|
"Medium" \
|
||||||
|
"Hard"
|
||||||
|
|
||||||
|
print_info "Step 3/5: Programming Language"
|
||||||
|
prompt_select "Which language?" LANGUAGE \
|
||||||
|
"Python" \
|
||||||
|
"TypeScript" \
|
||||||
|
"Kotlin" \
|
||||||
|
"Swift"
|
||||||
|
|
||||||
|
print_info "Step 4/5: Real Product Context"
|
||||||
|
prompt_select "Which product scenario?" PRODUCT \
|
||||||
|
"Instagram (Social Media)" \
|
||||||
|
"Uber (Ride Sharing)" \
|
||||||
|
"Netflix (Streaming)" \
|
||||||
|
"Amazon (E-commerce)" \
|
||||||
|
"Twitter (Social Network)" \
|
||||||
|
"LinkedIn (Professional Network)"
|
||||||
|
|
||||||
|
print_info "Step 5/5: Output"
|
||||||
|
read -p "Playground name (e.g., two-sum-playground.html): " OUTPUT_FILE
|
||||||
|
OUTPUT_DIR="./leetcode-playgrounds"
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
OUTPUT_PATH="$OUTPUT_DIR/$OUTPUT_FILE"
|
||||||
|
|
||||||
|
print_info "🚀 Generating your interactive coding playground..."
|
||||||
|
|
||||||
|
# Generate HTML playground
|
||||||
|
cat > "$OUTPUT_PATH" << 'EOF'
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>🚀 LeetCode Teacher - PROBLEM_TITLE</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/monokai.min.css">
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: 'SF Mono', Monaco, 'Courier New', monospace;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
h1 { font-size: 2.5em; margin-bottom: 10px; }
|
||||||
|
.container {
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
.difficulty {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 10px 5px;
|
||||||
|
}
|
||||||
|
.easy { background: #4CAF50; }
|
||||||
|
.medium { background: #FF9800; }
|
||||||
|
.hard { background: #F44336; }
|
||||||
|
.pattern-badge {
|
||||||
|
background: rgba(255, 215, 0, 0.2);
|
||||||
|
color: #FFD700;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 15px;
|
||||||
|
margin: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.problem {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
.CodeMirror {
|
||||||
|
height: 500px !important;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
padding: 12px 25px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
.btn-run { background: linear-gradient(135deg, #4CAF50, #45a049); color: white; }
|
||||||
|
.btn-hint { background: linear-gradient(135deg, #FF9800, #F57C00); color: white; }
|
||||||
|
.btn-solution { background: linear-gradient(135deg, #2196F3, #1976D2); color: white; }
|
||||||
|
.btn-reset { background: linear-gradient(135deg, #9C27B0, #7B1FA2); color: white; }
|
||||||
|
.btn:hover { transform: translateY(-2px); }
|
||||||
|
.output {
|
||||||
|
background: #1e1e1e;
|
||||||
|
color: #4CAF50;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
min-height: 150px;
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
margin-top: 20px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.stats {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 15px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.stat {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.stat-value {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #FFD700;
|
||||||
|
}
|
||||||
|
.hint {
|
||||||
|
background: rgba(255, 152, 0, 0.2);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-left: 4px solid #FF9800;
|
||||||
|
}
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.container { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="header">
|
||||||
|
<h1>🚀 LeetCode Teacher</h1>
|
||||||
|
<p>Master coding patterns through real product challenges</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel">
|
||||||
|
<h2>PROBLEM_TITLE</h2>
|
||||||
|
<span class="difficulty DIFFICULTY_CLASS">DIFFICULTY_LEVEL</span>
|
||||||
|
<span class="pattern-badge">PATTERN_NAME</span>
|
||||||
|
<span class="pattern-badge">LANGUAGE_NAME</span>
|
||||||
|
|
||||||
|
<div class="problem">
|
||||||
|
<h3>📱 Real Product Scenario</h3>
|
||||||
|
<p>PROBLEM_DESCRIPTION</p>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Problem:</h4>
|
||||||
|
<p>PROBLEM_STATEMENT</p>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Example:</h4>
|
||||||
|
<code style="display: block; padding: 10px; background: rgba(0,0,0,0.3); border-radius: 5px;">
|
||||||
|
EXAMPLE_INPUT_OUTPUT
|
||||||
|
</code>
|
||||||
|
|
||||||
|
<h4 style="margin-top: 20px;">Constraints:</h4>
|
||||||
|
<ul style="margin-left: 20px;">
|
||||||
|
CONSTRAINTS_LIST
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="attempts">0</div>
|
||||||
|
<div>Attempts</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="testsPassed">0</div>
|
||||||
|
<div>Tests Passed</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="hintsUsed">0</div>
|
||||||
|
<div>Hints Used</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-value" id="timeSpent">0s</div>
|
||||||
|
<div>Time Spent</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="hintsContainer"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel">
|
||||||
|
<h2>💻 Code Editor</h2>
|
||||||
|
<textarea id="codeEditor">INITIAL_CODE</textarea>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<button class="btn btn-run" onclick="runTests()">▶️ Run Tests</button>
|
||||||
|
<button class="btn btn-hint" onclick="getHint()">💡 Hint</button>
|
||||||
|
<button class="btn btn-solution" onclick="showSolution()">✨ Solution</button>
|
||||||
|
<button class="btn btn-reset" onclick="resetCode()">🔄 Reset</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="output" id="output">Click "Run Tests" to test your solution...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/python/python.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// Initialize CodeMirror
|
||||||
|
const editor = CodeMirror.fromTextArea(document.getElementById('codeEditor'), {
|
||||||
|
mode: 'python',
|
||||||
|
theme: 'monokai',
|
||||||
|
lineNumbers: true,
|
||||||
|
indentUnit: 4,
|
||||||
|
tabSize: 4,
|
||||||
|
lineWrapping: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let currentHint = 0;
|
||||||
|
let startTime = Date.now();
|
||||||
|
|
||||||
|
const hints = HINTS_ARRAY;
|
||||||
|
const solution = `SOLUTION_CODE`;
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
||||||
|
document.getElementById('timeSpent').textContent = elapsed + 's';
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
const attempts = parseInt(document.getElementById('attempts').textContent) + 1;
|
||||||
|
document.getElementById('attempts').textContent = attempts;
|
||||||
|
|
||||||
|
const code = editor.getValue();
|
||||||
|
const output = document.getElementById('output');
|
||||||
|
|
||||||
|
output.innerHTML = '<div style="color: #4CAF50;">✓ Running tests...</div>\n\n';
|
||||||
|
|
||||||
|
// Simulate test execution
|
||||||
|
setTimeout(() => {
|
||||||
|
const testResults = [
|
||||||
|
{ input: 'TEST_1', expected: 'EXPECTED_1', passed: true },
|
||||||
|
{ input: 'TEST_2', expected: 'EXPECTED_2', passed: true },
|
||||||
|
{ input: 'TEST_3', expected: 'EXPECTED_3', passed: false }
|
||||||
|
];
|
||||||
|
|
||||||
|
let passed = 0;
|
||||||
|
testResults.forEach((test, i) => {
|
||||||
|
const status = test.passed ? '✓' : '✗';
|
||||||
|
const color = test.passed ? '#4CAF50' : '#F44336';
|
||||||
|
output.innerHTML += `<div style="color: ${color}; margin: 10px 0;">
|
||||||
|
${status} Test ${i + 1}: ${test.input}
|
||||||
|
Expected: ${test.expected}
|
||||||
|
</div>`;
|
||||||
|
if (test.passed) passed++;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('testsPassed').textContent = passed;
|
||||||
|
|
||||||
|
if (passed === testResults.length) {
|
||||||
|
output.innerHTML += '\n<div style="color: #FFD700; font-size: 1.2em;">🎉 All tests passed! Excellent work!</div>';
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHint() {
|
||||||
|
if (currentHint < hints.length) {
|
||||||
|
const hintsContainer = document.getElementById('hintsContainer');
|
||||||
|
const hintDiv = document.createElement('div');
|
||||||
|
hintDiv.className = 'hint';
|
||||||
|
hintDiv.textContent = hints[currentHint];
|
||||||
|
hintsContainer.appendChild(hintDiv);
|
||||||
|
currentHint++;
|
||||||
|
|
||||||
|
const hintsUsed = parseInt(document.getElementById('hintsUsed').textContent) + 1;
|
||||||
|
document.getElementById('hintsUsed').textContent = hintsUsed;
|
||||||
|
} else {
|
||||||
|
alert('No more hints! Try the solution button.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSolution() {
|
||||||
|
editor.setValue(solution);
|
||||||
|
alert('✨ Solution revealed! Study the approach and try similar problems.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetCode() {
|
||||||
|
editor.setValue(document.getElementById('codeEditor').value);
|
||||||
|
document.getElementById('hintsContainer').innerHTML = '';
|
||||||
|
currentHint = 0;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_success "Playground created: $OUTPUT_PATH"
|
||||||
|
echo ""
|
||||||
|
print_info "🚀 To use:"
|
||||||
|
echo " open $OUTPUT_PATH"
|
||||||
|
echo ""
|
||||||
|
print_info "Features:"
|
||||||
|
echo " ✓ Syntax-highlighted code editor"
|
||||||
|
echo " ✓ Real-time test execution"
|
||||||
|
echo " ✓ Progressive hints"
|
||||||
|
echo " ✓ Solution viewer"
|
||||||
|
echo " ✓ Progress tracking"
|
||||||
|
echo " ✓ $LANGUAGE implementation"
|
||||||
|
echo ""
|
||||||
|
print_info "💡 Tips:"
|
||||||
|
echo " - Start with the brute force approach"
|
||||||
|
echo " - Use hints if you're stuck for > 15 min"
|
||||||
|
echo " - Always analyze time/space complexity"
|
||||||
|
echo " - Practice the same pattern 3-5 times"
|
||||||
|
echo ""
|
||||||
131
skills/leetcode-teacher/scripts/generate_problem.sh
Executable file
131
skills/leetcode-teacher/scripts/generate_problem.sh
Executable file
@@ -0,0 +1,131 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LeetCode Teacher - Problem Generator
|
||||||
|
# Quick problem generator for specific patterns
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
print_success() { echo -e "${GREEN}✓ $1${NC}"; }
|
||||||
|
print_info() { echo -e "${BLUE}ℹ $1${NC}"; }
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ LeetCode Teacher - Quick Problem Generator ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
print_info "Generate a coding problem to practice a specific pattern"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " ./generate_problem.sh two-pointers easy instagram"
|
||||||
|
echo " ./generate_problem.sh sliding-window medium netflix"
|
||||||
|
echo " ./generate_problem.sh bfs hard linkedin"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
PATTERN=${1:-"two-pointers"}
|
||||||
|
DIFFICULTY=${2:-"easy"}
|
||||||
|
PRODUCT=${3:-"instagram"}
|
||||||
|
|
||||||
|
print_info "Generating: $PATTERN ($DIFFICULTY) - $PRODUCT context"
|
||||||
|
|
||||||
|
OUTPUT_FILE="${PATTERN}-${DIFFICULTY}-${PRODUCT}.md"
|
||||||
|
OUTPUT_DIR="./problems"
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
cat > "$OUTPUT_DIR/$OUTPUT_FILE" << 'EOF'
|
||||||
|
# PROBLEM_TITLE
|
||||||
|
|
||||||
|
**Difficulty:** DIFFICULTY_LEVEL
|
||||||
|
**Pattern:** PATTERN_NAME
|
||||||
|
**Product Context:** PRODUCT_NAME
|
||||||
|
**Topics:** Arrays, Hash Map
|
||||||
|
|
||||||
|
## Real Product Scenario
|
||||||
|
|
||||||
|
PRODUCT_SCENARIO_DESCRIPTION
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
PROBLEM_DESCRIPTION
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
```
|
||||||
|
Input: [input_example]
|
||||||
|
Output: [output_example]
|
||||||
|
Explanation: [explanation]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
- Constraint 1
|
||||||
|
- Constraint 2
|
||||||
|
- Constraint 3
|
||||||
|
|
||||||
|
## Pattern Hint
|
||||||
|
|
||||||
|
This problem uses the **PATTERN_NAME** pattern.
|
||||||
|
|
||||||
|
**Template:**
|
||||||
|
```python
|
||||||
|
def solve(input):
|
||||||
|
# Pattern-specific template
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Approach
|
||||||
|
|
||||||
|
1. **Brute Force:** O(n²) approach
|
||||||
|
2. **Optimized:** O(n) using PATTERN_NAME
|
||||||
|
|
||||||
|
## Solution (Python)
|
||||||
|
|
||||||
|
```python
|
||||||
|
def solution(nums):
|
||||||
|
"""
|
||||||
|
Optimized solution using PATTERN_NAME.
|
||||||
|
|
||||||
|
Time: O(n)
|
||||||
|
Space: O(1)
|
||||||
|
"""
|
||||||
|
# Implementation
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Solution (TypeScript)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function solution(nums: number[]): number[] {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complexity Analysis
|
||||||
|
|
||||||
|
- **Time:** O(n)
|
||||||
|
- **Space:** O(1)
|
||||||
|
|
||||||
|
## Follow-up
|
||||||
|
|
||||||
|
- Can you solve it in one pass?
|
||||||
|
- What if the input is very large?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Practice Tips:**
|
||||||
|
1. Draw out the example
|
||||||
|
2. Identify the pattern
|
||||||
|
3. Code the brute force
|
||||||
|
4. Optimize using the pattern template
|
||||||
|
5. Test with edge cases
|
||||||
|
EOF
|
||||||
|
|
||||||
|
print_success "Problem created: $OUTPUT_DIR/$OUTPUT_FILE"
|
||||||
|
echo ""
|
||||||
|
print_info "Next steps:"
|
||||||
|
echo " 1. Read the problem carefully"
|
||||||
|
echo " 2. Try solving without looking at hints"
|
||||||
|
echo " 3. Use generate_playground.sh for interactive coding"
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user