Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VERSION = 3.13
PROBLEM ?= reverse_nodes_in_k_group
PROBLEM ?= number_of_connected_components_in_an_undirected_graph
FORCE ?= 0
COMMA := ,

Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ A Python package to generate professional LeetCode practice environments. Featur

- **grind-75** - Essential coding interview questions from [Grind 75](https://www.techinterviewhandbook.org/grind75/) ✅ Complete
- **grind** - Extended Grind collection including all Grind 75 plus additional problems 🚧 Partial
- **blind-75** - Original [Blind 75](https://leetcode.com/problem-list/xi4ci4ig/) curated list 🚧 Partial
- **blind-75** - Original [Blind 75](https://leetcode.com/problem-list/xi4ci4ig/) curated list ✅ Complete
- **neetcode-150** - Comprehensive [NeetCode 150](https://neetcode.io/practice) problem set 🚧 Partial
- **algo-master-75** - Curated algorithmic mastery problems 🚧 Partial

**Coverage**: 120+ unique problems across all major coding interview topics and difficulty levels.
**Coverage**: 130+ unique problems across all major coding interview topics and difficulty levels.

**Note**: Some problem sets are partially covered. We're actively working to complete all collections. [Contributions welcome!](https://github.com/wislertt/leetcode-py/blob/main/CONTRIBUTING.md)

Expand Down Expand Up @@ -82,11 +82,11 @@ lcpy gen --problem-tag neetcode-150 --output leetcode # Generate NeetCode 150
lcpy gen --problem-tag blind-75 --output leetcode # Generate Blind 75 problems
```

![Problem Generation](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/problems-generation.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/problems-generation.png" alt="Problem Generation" style="pointer-events: none;">

_Bulk generation output showing "Generated problem:" messages for all 75 Grind problems_

![Problem Generation 2](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/problems-generation-2.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/problems-generation-2.png" alt="Problem Generation 2" style="pointer-events: none;">

_Generated folder structure showing all 75 problem directories after command execution_

Expand All @@ -104,19 +104,19 @@ leetcode/two_sum/
└── __init__.py # Package marker
```

![README Example](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/readme-example.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/readme-example.png" alt="README Example" style="pointer-events: none;">

_README format that mirrors LeetCode's problem description layout_

![Solution Boilerplate](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/solution-boilerplate.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/solution-boilerplate.png" alt="Solution Boilerplate" style="pointer-events: none;">

_Solution boilerplate with type hints and TODO placeholder_

![Test Example](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/test-example.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/test-example.png" alt="Test Example" style="pointer-events: none;">

_Comprehensive parametrized tests with 10+ test cases - executable and debuggable in local development environment_

![Test Logging](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/logs-in-test-solution.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/logs-in-test-solution.png" alt="Test Logging" style="pointer-events: none;">

_Beautiful colorful test output with loguru integration for enhanced debugging and test result visualization_

Expand All @@ -141,21 +141,21 @@ Professional-grade visualization for debugging complex data structures with dual

#### Jupyter Notebook Integration (HTML Rendering)

![Tree Visualization](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/tree-viz.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/tree-viz.png" alt="Tree Visualization" style="pointer-events: none;">

_Interactive tree visualization using Graphviz SVG rendering in Jupyter notebooks_

![LinkedList Visualization](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/linkedlist-viz.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/linkedlist-viz.png" alt="LinkedList Visualization" style="pointer-events: none;">

_Professional linked list visualization with Graphviz in Jupyter environment_

#### Terminal/Console Output (String Rendering)

![Tree String Visualization](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/tree-str-viz.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/tree-str-viz.png" alt="Tree String Visualization" style="pointer-events: none;">

_Clean ASCII tree rendering using anytree for terminal debugging and logging_

![LinkedList String Visualization](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/linkedlist-str-viz.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/linkedlist-str-viz.png" alt="LinkedList String Visualization" style="pointer-events: none;">

_Simple arrow-based list representation for console output and test debugging_

Expand All @@ -166,7 +166,7 @@ _Simple arrow-based list representation for console output and test debugging_
- **Repository State**: This repo converts them to Python files (`.py`) for better version control
- **Dual Rendering**: Automatic HTML visualization in notebooks, clean string output in terminals

![Notebook Example](https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/notebook-example.png)
<img src="https://raw.githubusercontent.com/wislertt/leetcode-py/main/docs/images/notebook-example.png" alt="Notebook Example" style="pointer-events: none;">

_Interactive multi-cell playground with rich data structure visualization for each problem_

Expand Down Expand Up @@ -301,8 +301,8 @@ make gen-all-problems # Regenerate all problems (destructive)

## 🏗️ Architecture

- **Template-Driven**: JSON templates in `.templates/leetcode/json/` drive code generation
- **Cookiecutter Integration**: Uses `.templates/leetcode/{{cookiecutter.problem_name}}/` template for consistent file structure
- **Template-Driven**: JSON templates in `leetcode_py/cli/resources/leetcode/json/problems/` drive code generation
- **Cookiecutter Integration**: Uses `leetcode_py/cli/resources/leetcode/{{cookiecutter.problem_name}}/` template for consistent file structure
- **Automated Scraping**: LLM-assisted problem data extraction from LeetCode
- **Version Control Friendly**: Python files by default, optional notebook support

Expand Down
2 changes: 1 addition & 1 deletion docs/cli-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Available tags for bulk operations:

- `grind-75` - Essential 75 coding interview problems from [Grind 75](https://www.techinterviewhandbook.org/grind75/) ✅ Complete
- `grind` - Extended Grind collection (100+ problems) including all Grind 75 plus additional problems 🚧 Partial
- `blind-75` - Original [Blind 75](https://leetcode.com/discuss/general-discussion/460599/blind-75-leetcode-questions) curated list 🚧 Partial
- `blind-75` - Original [Blind 75](https://leetcode.com/discuss/general-discussion/460599/blind-75-leetcode-questions) curated list ✅ Complete
- `neetcode-150` - Comprehensive [NeetCode 150](https://neetcode.io/practice) problem set (150+ problems) 🚧 Partial
- `algo-master-75` - Curated algorithmic mastery problems (75 problems) 🚧 Partial

Expand Down
39 changes: 39 additions & 0 deletions leetcode/encode_and_decode_strings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Encode and Decode Strings

**Difficulty:** Medium
**Topics:** Array, String, Design
**Tags:** blind-75

**LeetCode:** [Problem 271](https://leetcode.com/problems/encode-and-decode-strings/description/)

## Problem Description

Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.

## Examples

### Example 1:

```
Input: dummy_input = ["Hello","World"]
Output: "Hello,World"
Explanation: Machine 1:
Codec encoder = new Codec();
String msg = encoder.encode(strs);
Machine 1 ---msg---> Machine 2
Machine 2:
Codec decoder = new Codec();
String[] strs = decoder.decode(msg);
```

## Constraints

- 1 <= strs.length <= 200
- 0 <= strs[i].length <= 200
- strs[i] contains any possible characters out of 256 valid ASCII characters.

**Note:**

- The string may contain any possible characters out of 256 valid ASCII characters. Your algorithm should be generalized enough to work on any possible characters.
- Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
- Do not rely on any library method such as eval or serialize methods. You should implement your own encode/decode algorithm.
Empty file.
10 changes: 10 additions & 0 deletions leetcode/encode_and_decode_strings/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def run_encode_decode(solution_class: type, strs: list[str]):
implementation = solution_class()
encoded = implementation.encode(strs)
decoded = implementation.decode(encoded)
return decoded


def assert_encode_decode(result: list[str], expected: list[str]) -> bool:
assert result == expected
return True
29 changes: 29 additions & 0 deletions leetcode/encode_and_decode_strings/playground.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.17.3
# kernelspec:
# display_name: leetcode-py-py3.13
# language: python
# name: python3
# ---

# %%
from helpers import assert_encode_decode, run_encode_decode
from solution import Solution

# %%
# Example test case
strs = ["Hello", "World"]
expected = strs

# %%
result = run_encode_decode(Solution, strs)
result

# %%
assert_encode_decode(result, expected)
33 changes: 33 additions & 0 deletions leetcode/encode_and_decode_strings/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Solution:

# Time: O(n)
# Space: O(n)
def encode(self, strs: list[str]) -> str:
encoded = ""
for s in strs:
# Format: length + '#' + string
encoded += str(len(s)) + "#" + s
return encoded

# Time: O(n)
# Space: O(n)
def decode(self, s: str) -> list[str]:
decoded = []
i = 0

while i < len(s):
# Find the delimiter '#'
j = i
while s[j] != "#":
j += 1

# Extract length
length = int(s[i:j])

# Extract string of that length
decoded.append(s[j + 1 : j + 1 + length])

# Move to next encoded string
i = j + 1 + length

return decoded
41 changes: 41 additions & 0 deletions leetcode/encode_and_decode_strings/test_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import pytest

from leetcode_py import logged_test

from .helpers import assert_encode_decode, run_encode_decode
from .solution import Solution


class TestEncodeAndDecodeStrings:
def setup_method(self):
self.solution = Solution()

@logged_test
@pytest.mark.parametrize(
"strs",
[
["Hello", "World"],
["abc", "def"],
[""],
["a", "b", "c"],
["", "", ""],
["hello", "", "world"],
["a#b", "c#d"],
["4#3hello", "world"],
["#", "##", "###"],
["abc123", "def456", "ghi789"],
["special!@#$%^&*()"],
["with spaces", "and tabs\t", "and newlines\n"],
["unicode测试", "emoji😀"],
["very long string " * 10],
["a" * 200],
[],
["single"],
["comma,separated", "values,here"],
["pipe|separated", "values|here"],
["colon:separated", "values:here"],
],
)
def test_encode_decode(self, strs: list[str]):
result = run_encode_decode(Solution, strs)
assert_encode_decode(result, strs)
38 changes: 38 additions & 0 deletions leetcode/graph_valid_tree/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Graph Valid Tree

**Difficulty:** Medium
**Topics:** Depth-First Search, Breadth-First Search, Union Find, Graph
**Tags:** blind-75

**LeetCode:** [Problem 261](https://leetcode.com/problems/graph-valid-tree/description/)

## Problem Description

Given `n` nodes labeled from `0` to `n-1` and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.

## Examples

### Example 1:

```
Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]]
Output: true
```

### Example 2:

```
Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
Output: false
```

## Constraints

- 0 <= n <= 2000
- 0 <= edges.length <= 5000
- edges[i].length == 2
- 0 <= ai, bi < n
- ai != bi
- There are no self-loops or repeated edges.

**Note:** you can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0,1] is the same as [1,0] and thus will not appear together in edges.
Empty file.
8 changes: 8 additions & 0 deletions leetcode/graph_valid_tree/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def run_valid_tree(solution_class: type, n: int, edges: list[list[int]]):
implementation = solution_class()
return implementation.valid_tree(n, edges)


def assert_valid_tree(result: bool, expected: bool) -> bool:
assert result == expected
return True
30 changes: 30 additions & 0 deletions leetcode/graph_valid_tree/playground.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.17.3
# kernelspec:
# display_name: leetcode-py-py3.13
# language: python
# name: python3
# ---

# %%
from helpers import assert_valid_tree, run_valid_tree
from solution import Solution

# %%
# Example test case
n = 5
edges = [[0, 1], [0, 2], [0, 3], [1, 4]]
expected = True

# %%
result = run_valid_tree(Solution, n, edges)
result

# %%
assert_valid_tree(result, expected)
33 changes: 33 additions & 0 deletions leetcode/graph_valid_tree/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Solution:

# Time: O(n + e)
# Space: O(n + e)
def valid_tree(self, n: int, edges: list[list[int]]) -> bool:
# Edge case: empty graph is a valid tree
if n == 0:
return True

# A valid tree must have exactly n-1 edges
if len(edges) != n - 1:
return False

# Build adjacency list
graph: list[list[int]] = [[] for _ in range(n)]
for u, v in edges:
graph[u].append(v)
graph[v].append(u)

# DFS to check connectivity
visited = set()

def dfs(node: int) -> None:
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor)

# Start DFS from node 0
dfs(0)

# Check if all nodes are visited (connected)
return len(visited) == n
Loading