Skip to content

Conversation

@vikahaze
Copy link
Collaborator

@vikahaze vikahaze commented Dec 4, 2025

Summary

This PR adds solutions and explanations for 15 LeetCode problems covering various topics including bit manipulation, graph algorithms, dynamic programming, trees, and data structures.

Problems Added

2211. Count Collisions on a Road (Medium)

  • Approach: Remove leading L's and trailing R's, count non-stationary cars in the middle section
  • Complexity: O(n) time, O(n) space
  • Status: Accepted (119/119 test cases)

190. Reverse Bits (Easy)

  • Approach: Extract each bit and place it in the reversed position using bit manipulation
  • Complexity: O(1) time, O(1) space
  • Status: Accepted (600/600 test cases)

191. Number of 1 Bits (Easy)

  • Approach: Use n & (n-1) trick to remove rightmost set bit, count iterations
  • Complexity: O(k) where k is number of set bits, O(1) space
  • Status: Accepted (598/598 test cases)

201. Bitwise AND of Numbers Range (Medium)

  • Approach: Find common prefix by right-shifting until left equals right, then shift back
  • Complexity: O(log n) time, O(1) space
  • Status: Solution written (rate limited during submission)

202. Happy Number (Easy)

  • Approach: Use set to detect cycles, repeatedly calculate sum of squares of digits
  • Complexity: O(log n) time, O(log n) space
  • Status: Accepted (420/420 test cases)

207. Course Schedule (Medium)

  • Approach: Topological sort using Kahn's algorithm (BFS) to detect cycles
  • Complexity: O(V + E) time, O(V + E) space
  • Status: Accepted (54/54 test cases)

209. Minimum Size Subarray Sum (Medium)

  • Approach: Sliding window (two pointers) to find minimal length subarray
  • Complexity: O(n) time, O(1) space
  • Status: Solution written (session expired during submission)

210. Course Schedule II (Medium)

  • Approach: Topological sort using Kahn's algorithm, build ordering as we process
  • Complexity: O(V + E) time, O(V + E) space
  • Status: Accepted (47/47 test cases)

211. Design Add and Search Words Data Structure (Medium)

  • Approach: Trie with DFS for wildcard (dot) matching
  • Complexity: O(m) for addWord, O(m * 26^k) for search with k dots
  • Status: Accepted (29/29 test cases)

212. Word Search II (Hard)

  • Approach: Build trie from words, use backtracking with trie to search board
  • Complexity: O(M * N * 4^L) time with early pruning
  • Status: Accepted (65/65 test cases)

221. Maximal Square (Medium)

  • Approach: Dynamic programming - dp[i][j] = min of three adjacent squares + 1
  • Complexity: O(m * n) time, O(m * n) space
  • Status: Accepted (81/81 test cases)

222. Count Complete Tree Nodes (Easy)

  • Approach: Use complete tree property - compare left/right heights to skip full subtrees
  • Complexity: O(log² n) time, O(log n) space
  • Status: Accepted (18/18 test cases)

224. Basic Calculator (Hard)

  • Approach: Stack-based evaluation with sign tracking for parentheses
  • Complexity: O(n) time, O(n) space
  • Status: Solution written (rate limited during submission)

226. Invert Binary Tree (Easy)

  • Approach: Recursively swap left and right children at each node
  • Complexity: O(n) time, O(h) space
  • Status: Accepted (77/77 test cases)

295. Find Median from Data Stream (Hard)

  • Approach: Two heaps (max-heap for smaller half, min-heap for larger half)
  • Complexity: O(log n) for addNum, O(1) for findMedian
  • Status: Accepted (22/22 test cases)

Files Changed

  • 15 solution files: solutions/<problem-number>/01.py
  • 15 explanation files: explanations/<problem-number>/en.md

All explanations follow the structured format defined in the workflow rules, including strategy, complexity analysis, and step-by-step walkthroughs.

Summary by Sourcery

Add Python solutions and accompanying English explanations for multiple LeetCode problems across arrays, graphs, trees, bit manipulation, and data structures, and align an existing solution with the LeetCode class-based interface.

New Features:

  • Implement solution and explanation for counting collisions on a road (problem 2211).
  • Implement solution and explanation for reversing bits of a 32-bit integer (problem 190).
  • Implement solution and explanation for counting set bits in an integer (problem 191).
  • Implement solution and explanation for bitwise AND over a numeric range (problem 201).
  • Implement solution and explanation for determining if a number is happy (problem 202).
  • Implement solution and explanation for detecting if all courses can be finished using topological sort (problem 207).
  • Implement solution and explanation for minimum-size subarray sum using a sliding window (problem 209).
  • Implement solution and explanation for returning a valid course ordering via topological sort (problem 210).
  • Implement trie-based add/search word data structure solution and explanation (problem 211).
  • Implement trie + backtracking board word search solution and explanation (problem 212).
  • Implement dynamic-programming maximal square solution and explanation (problem 221).
  • Implement complete binary tree node-counting solution and explanation (problem 222).
  • Implement stack-based basic calculator solution and explanation (problem 224).
  • Implement recursive invert binary tree solution and explanation (problem 226).
  • Implement two-heap median-from-data-stream solution and explanation (problem 295).

Enhancements:

  • Refactor the invert-binary-tree implementation into a LeetCode-compatible Solution class method interface (problem 226).

Documentation:

  • Add structured English explanations for newly added LeetCode problem solutions, including strategy, complexity, and walkthrough sections.

Summary by CodeRabbit

  • New Features

    • Added 15 new algorithm solutions covering bitwise operations, graph traversal, dynamic programming, tree operations, and data stream processing.
  • Documentation

    • Added 15 comprehensive explanation documents with complexity analysis, strategies, step-by-step walkthroughs, and examples for various algorithmic problems.

✏️ Tip: You can customize this high-level summary in your review settings.

… 207, 209, 210, 211, 212, 221, 222, 224, 226, 295
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 4, 2025

Reviewer's Guide

Adds accepted Python solutions and detailed English explanations for 15 LeetCode problems across bit manipulation, trees, graphs, DP, and data structures, and modernizes the existing invert-binary-tree solution to LeetCode’s class-based interface.

Class diagram for trie-based word search and dictionary solutions

classDiagram

class TrieNode {
  dict children
  bool is_end
  str word
  __init__()
}

class WordDictionary {
  TrieNode root
  __init__()
  addWord(word: str) void
  search(word: str) bool
}

class SolutionWordSearchII {
  findWords(board: List_List_str, words: List_str) List_str
  dfs(row: int, col: int, node: TrieNode) void
}

WordDictionary --> TrieNode : uses
SolutionWordSearchII --> TrieNode : builds_trie_from_words

%% Representing the LeetCode class name for problem 212
class SolutionWordSearchII as Solution_212
Loading

Class diagram for MedianFinder data stream structure

classDiagram

class MedianFinder {
  list max_heap
  list min_heap
  __init__()
  addNum(num: int) void
  findMedian() float
}

MedianFinder : max_heap stores_negative_values
MedianFinder : min_heap stores_positive_values
Loading

Class diagram for binary tree solutions (invert tree and count complete nodes)

classDiagram

class TreeNode {
  int val
  TreeNode left
  TreeNode right
  __init__(val: int, left: TreeNode, right: TreeNode)
}

class SolutionInvertTree {
  invertTree(root: TreeNode) TreeNode
}

class SolutionCountNodes {
  countNodes(root: TreeNode) int
  get_height(node: TreeNode) int
}

SolutionInvertTree --> TreeNode : manipulates
SolutionCountNodes --> TreeNode : reads_structure

%% Representing LeetCode class names
class SolutionInvertTree as Solution_226
class SolutionCountNodes as Solution_222
Loading

File-Level Changes

Change Details Files
Implement efficient bit-manipulation utilities for reversing bits, counting set bits, and computing bitwise AND over a range.
  • Add O(1) 32-iteration bit reversal using shifting and masking.
  • Add hamming weight using repeated n &= n-1 to strip lowest set bit.
  • Add range bitwise AND by right-shifting left/right to find common prefix then shifting back.
solutions/190/01.py
solutions/191/01.py
solutions/201/01.py
explanations/190/en.md
explanations/191/en.md
explanations/201/en.md
Implement happy-number detection using cycle detection via a set.
  • Iteratively compute sum of digit squares until reaching 1 or a repeated value.
  • Track seen intermediate values in a set to detect cycles and short-circuit unhappy numbers.
solutions/202/01.py
explanations/202/en.md
Implement course-schedule feasibility and ordering using Kahn’s topological sort.
  • Build adjacency lists and in-degree arrays from prerequisite pairs.
  • Use a queue-based BFS to process zero in-degree nodes and detect cycles for the feasibility check.
  • Produce a valid topological ordering when all courses can be scheduled.
solutions/207/01.py
solutions/210/01.py
explanations/207/en.md
explanations/210/en.md
Implement sliding-window solution for minimum-size subarray with sum at least target.
  • Maintain moving window with left/right pointers and running sum.
  • Shrink window greedily when sum exceeds target to track minimal length, handling no-solution via sentinel infinity.
solutions/209/01.py
explanations/209/en.md
Implement trie-based word dictionary with wildcard search and trie+DFS word search on a grid.
  • Create TrieNode class with children map and end-of-word flag or stored word string.
  • Support addWord in O(m) and wildcard search using DFS branching on '.' across children.
  • Build a trie from the word list and perform board DFS with in-place marking, early pruning, and node deletion for Word Search II.
solutions/211/01.py
solutions/212/01.py
explanations/211/en.md
explanations/212/en.md
Implement DP solution for maximal square of 1s in a binary matrix.
  • Allocate 2D DP array storing side length of largest square ending at each cell.
  • Transition using 1 + min(top, left, top-left) for '1' cells, and track global max side to return area.
solutions/221/01.py
explanations/221/en.md
Implement node-counting in a complete binary tree using height-based pruning.
  • Compute subtree height by walking left children only.
  • Use left/right height comparison to determine which subtree is perfect and derive its size via bit shift, recursing into the other subtree.
solutions/222/01.py
explanations/222/en.md
Implement collision counting on a road by trimming non-colliding edges and counting active cars.
  • Strip leading L and trailing R characters since they never collide.
  • Iterate remaining substring and count non-stationary cars (L/R) to equal collision count, returning 0 when middle is empty.
solutions/2211/01.py
explanations/2211/en.md
Implement stack-based basic calculator supporting +, -, parentheses, and spaces.
  • Scan expression once, building multi-digit numbers, applying current sign when encountering operators.
  • On '(', push current result and sign; on ')', finalize current number, apply stacked sign, and merge with previous result.
  • Return final accumulated result plus last pending number.
solutions/224/01.py
explanations/224/en.md
Implement recursive binary-tree utilities: invert a binary tree and count nodes in a complete tree.
  • Refactor invert-binary-tree solution into LeetCode-style Solution class with recursive child-swap and base case for null nodes.
  • Document recursion depth, time/space complexities, and example trace for the invert-binary-tree operation.
solutions/226/01.py
explanations/226/en.md
Implement streaming median finder using two heaps.
  • Maintain a max-heap for the lower half (via negated values) and a min-heap for the upper half.
  • Balance heap sizes after each insertion and compute the median from the roots in O(1).
solutions/295/01.py
explanations/295/en.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

New documentation and Python implementations for 16 algorithms covering bit manipulation, graph algorithms, dynamic programming, tree operations, and data structures. Each algorithm includes a detailed explanation file (strategy, complexity, examples) paired with a Python solution file. No modifications to existing code; only new files added.

Changes

Cohort / File(s) Summary
Bit Manipulation Algorithms
explanations/190/en.md, explanations/191/en.md, explanations/201/en.md
solutions/190/01.py, solutions/191/01.py, solutions/201/01.py
Documents and implements bit-reversal (O(1) time/space), Hamming weight counting via Brian Kernighan's algorithm, and bitwise AND of a range via common prefix detection (O(log n) time).
Topological Sort – Course Scheduling
explanations/207/en.md, explanations/210/en.md
solutions/207/01.py, solutions/210/01.py
Explains and implements Kahn's algorithm for course prerequisite ordering. 207 returns boolean (can finish all); 210 returns sorted order or empty list if cycle detected.
Array & DP Algorithms
explanations/209/en.md, explanations/221/en.md, explanations/222/en.md
solutions/209/01.py, solutions/221/01.py, solutions/222/01.py
Covers sliding-window minimal subarray (O(n) time), maximal square DP (O(m×n) time), and complete binary tree node counting via height comparison (O(log² n) time).
Search & Dictionary with Trie
explanations/211/en.md, explanations/212/en.md
solutions/211/01.py, solutions/212/01.py
Implements wildcard dictionary search (211) and word search on board (212) using Trie structure with DFS pattern matching and backtracking.
Number Properties & Expression Evaluation
explanations/202/en.md, explanations/2211/en.md, explanations/224/en.md
solutions/202/01.py, solutions/2211/01.py, solutions/224/01.py
Happy number cycle detection, car collision counting via string trimming, and arithmetic expression evaluation with parentheses using stack-based approach.
Tree Algorithms
explanations/226/en.md
solutions/226/01.py
Converts top-level function to class method for recursive binary tree inversion.
Data Structure – Median Finder
explanations/295/en.md
solutions/295/01.py
Two-heap (max and min) structure for online median computation with O(log n) insertion and O(1) retrieval.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • solutions/212/01.py – Word Search II with Trie, DFS, backtracking, and pruning logic; verify correctness of node pruning and word deduplication strategy.
  • solutions/210/01.py & solutions/207/01.py – Topological sort implementations; confirm proper graph construction, in-degree initialization, and cycle detection handling.
  • solutions/221/01.py – DP state transitions and boundary conditions; verify dp[i][j] logic and result computation.
  • solutions/222/01.py – Complete tree height-based counting; ensure height computation and recursive formula correctly exploit complete tree properties.
  • solutions/211/01.py – Trie construction and wildcard DFS recursion; confirm dot-character exploration and end-of-word detection.
  • solutions/224/01.py – Stack-based expression parsing with nested parentheses; verify sign/result handling for all operators and edge cases.
  • Consistency across explanations and solutions – Ensure documentation examples match implementation behavior across all 16 problem pairs.

Suggested reviewers

  • romankurnovskii

Poem

🐰 Sixteen algorithms bloom so bright,
From bits that flip to trees in flight,
A Trie, a heap, a topological dance,
Each solution gets its explanatory chance—
Codey wonders if they'll all align,
A patchwork quilt of logic, refined!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title comprehensively describes the primary change—adding 15 LeetCode problem solutions and explanations across diverse algorithmic topics.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch problems-2211-190-191-201-202-207-209-210-211-212-221-222-224-226-295

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • In both canFinish (207/01.py) and findOrder (210/01.py) you’re using a Python list as a queue with pop(0), which is O(n) per pop; consider switching to collections.deque and using popleft() to keep the BFS truly O(V + E).
  • In the Word Search II solution (212/01.py), TrieNode.children is an untyped dict and dfs accesses node.children[char] directly; adding a type alias for the trie node and annotating children would make the data structure clearer and help static analysis catch misuse.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In both `canFinish` (207/01.py) and `findOrder` (210/01.py) you’re using a Python list as a queue with `pop(0)`, which is O(n) per pop; consider switching to `collections.deque` and using `popleft()` to keep the BFS truly O(V + E).
- In the Word Search II solution (212/01.py), `TrieNode.children` is an untyped dict and `dfs` accesses `node.children[char]` directly; adding a type alias for the trie node and annotating `children` would make the data structure clearer and help static analysis catch misuse.

## Individual Comments

### Comment 1
<location> `solutions/207/01.py:14-21` </location>
<code_context>
+            in_degree[course] += 1
+        
+        # Find all courses with no prerequisites
+        queue = []
+        for i in range(numCourses):
+            if in_degree[i] == 0:
+                queue.append(i)
+        
+        count = 0
+        while queue:
+            course = queue.pop(0)
+            count += 1
+            
</code_context>

<issue_to_address>
**suggestion (performance):** Using list.pop(0) for the queue leads to O(n²) behavior; a deque would be more efficient.

Because lists shift all elements on `pop(0)`, each dequeue is O(n), making the overall traversal O(n²) for large `numCourses`. `collections.deque.popleft()` keeps these queue operations O(1).

Suggested implementation:

```python
from collections import deque

class Solution:

```

To fully implement the deque-based queue:

1. Locate the section in `canFinish` where the queue is created and initialized. It likely looks something like:
   ```python
   queue = []
   for i in range(numCourses):
       if in_degree[i] == 0:
           queue.append(i)
   ```
   Change this to:
   ```python
   queue = deque()
   for i in range(numCourses):
       if in_degree[i] == 0:
           queue.append(i)
   ```
   (`append` remains the same; only the type changes.)

2. Locate the loop where elements are dequeued, which should currently look like:
   ```python
   while queue:
       course = queue.pop(0)
       count += 1
       # ...
   ```
   Change the dequeue to use `popleft()`:
   ```python
   while queue:
       course = queue.popleft()
       count += 1
       # ...
   ```

These changes will ensure the BFS/topological sort uses `collections.deque` with O(1) enqueue/dequeue instead of list `pop(0)` with O(n) behavior.
</issue_to_address>

### Comment 2
<location> `solutions/210/01.py:14-21` </location>
<code_context>
+            in_degree[course] += 1
+        
+        # Find all courses with no prerequisites
+        queue = []
+        for i in range(numCourses):
+            if in_degree[i] == 0:
+                queue.append(i)
+        
+        count = 0
+        while queue:
+            course = queue.pop(0)
+            count += 1
+            
</code_context>

<issue_to_address>
**suggestion (performance):** As in canFinish, using pop(0) on a list for the BFS queue is inefficient.

Here `queue.pop(0)` is O(n) per pop. Using `collections.deque` and `popleft()` would make the BFS queue operations O(1), which scales better for large graphs.

Suggested implementation:

```python
        # Find all courses with no prerequisites
        queue = deque()
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        count = 0
        while queue:
            course = queue.popleft()
            count += 1

```

To fully implement this change, ensure that `deque` is imported at the top of `solutions/210/01.py`:

```python
from collections import deque
```

If there is already an import section, add this import alongside the others.
</issue_to_address>

### Comment 3
<location> `explanations/190/en.md:6` </location>
<code_context>
+### Strategy (The "Why")
+
+**1.1 Constraints & Complexity:**
+- **Constraints:** We're working with a 32-bit unsigned integer. The input `n` ranges from 0 to 2^31 - 2 and is always even.
+- **Time Complexity:** O(1) - We iterate exactly 32 times regardless of input size.
+- **Space Complexity:** O(1) - We use only a constant amount of extra space.
</code_context>

<issue_to_address>
**issue:** Constraints for `n` (range and "always even") look incorrect for this problem.

The constraint line describes `n` as 0 to 2^31 - 2 and always even, which doesn’t match a 32-bit unsigned integer or typical bit-reversal specs. Please adjust the upper bound (e.g., 2^31 - 1 or 2^32 - 1, per the intended spec) and drop the “always even” condition unless the problem explicitly requires it.
</issue_to_address>

### Comment 4
<location> `explanations/191/en.md:6-9` </location>
<code_context>
+### Strategy (The "Why")
+
+**1.1 Constraints & Complexity:**
+- **Constraints:** The input `n` is a positive integer from 1 to 2^31 - 1.
+- **Time Complexity:** O(k) where k is the number of set bits (1s) in the binary representation. In worst case, this is O(32) = O(1) for 32-bit integers.
+- **Space Complexity:** O(1) - We use only a constant amount of extra space.
+- **Edge Case:** If `n = 0`, there are no set bits, so the result is 0.
+
+**1.2 High-level approach:**
</code_context>

<issue_to_address>
**issue:** Constraints and edge-case description are inconsistent regarding whether `n = 0` is allowed.

The constraints say `n` is in [1, 2^31 - 1], but the edge-case section handles `n = 0`. Please either update the constraints to include 0 or remove/rephrase the `n = 0` case so the allowed range and examples align.
</issue_to_address>

### Comment 5
<location> `solutions/207/01.py:14` </location>
<code_context>
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # Build adjacency list
        graph = [[] for _ in range(numCourses)]
        in_degree = [0] * numCourses

        for course, prereq in prerequisites:
            graph[prereq].append(course)
            in_degree[course] += 1

        # Find all courses with no prerequisites
        queue = []
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        count = 0
        while queue:
            course = queue.pop(0)
            count += 1

            # Reduce in-degree of dependent courses
            for next_course in graph[course]:
                in_degree[next_course] -= 1
                if in_degree[next_course] == 0:
                    queue.append(next_course)

        return count == numCourses

</code_context>

<issue_to_address>
**issue (code-quality):** Convert for loop into list comprehension ([`list-comprehension`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/list-comprehension/))
</issue_to_address>

### Comment 6
<location> `solutions/210/01.py:14` </location>
<code_context>
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        # Build adjacency list
        graph = [[] for _ in range(numCourses)]
        in_degree = [0] * numCourses

        for course, prereq in prerequisites:
            graph[prereq].append(course)
            in_degree[course] += 1

        # Find all courses with no prerequisites
        queue = []
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        res = []
        while queue:
            course = queue.pop(0)
            res.append(course)

            # Reduce in-degree of dependent courses
            for next_course in graph[course]:
                in_degree[next_course] -= 1
                if in_degree[next_course] == 0:
                    queue.append(next_course)

        return res if len(res) == numCourses else []

</code_context>

<issue_to_address>
**issue (code-quality):** Convert for loop into list comprehension ([`list-comprehension`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/list-comprehension/))
</issue_to_address>

### Comment 7
<location> `solutions/2211/01.py:7-18` </location>
<code_context>
    def countCollisions(self, directions: str) -> int:
        # Remove leading L's (moving left, will never collide)
        # Remove trailing R's (moving right, will never collide)
        # Only cars in the middle section will collide
        directions = directions.lstrip('L').rstrip('R')

        if not directions:
            return 0

        res = 0
        # Count all non-stationary cars in the middle section
        # Each R or L in the middle will eventually collide
        for char in directions:
            if char != 'S':
                res += 1

        return res

</code_context>

<issue_to_address>
**suggestion (code-quality):** We've found these issues:

- Convert for loop into call to sum() ([`sum-comprehension`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/sum-comprehension/))
- Lift code into else after jump in control flow ([`reintroduce-else`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/reintroduce-else/))
- Replace if statement with if expression ([`assign-if-exp`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/assign-if-exp/))
- Inline variable that is immediately returned ([`inline-immediately-returned-variable`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/inline-immediately-returned-variable/))

```suggestion

        return 0 if not directions else sum(1 for char in directions if char != 'S')
```
</issue_to_address>

### Comment 8
<location> `solutions/224/01.py:20` </location>
<code_context>
    def calculate(self, s: str) -> int:
        stack = []
        res = 0
        num = 0
        sign = 1

        for char in s:
            if char.isdigit():
                num = num * 10 + int(char)
            elif char == '+':
                res += sign * num
                num = 0
                sign = 1
            elif char == '-':
                res += sign * num
                num = 0
                sign = -1
            elif char == '(':
                stack.append(res)
                stack.append(sign)
                res = 0
                sign = 1
            elif char == ')':
                res += sign * num
                num = 0
                res *= stack.pop()  # pop sign
                res += stack.pop()  # pop previous result

        return res + sign * num

</code_context>

<issue_to_address>
**issue (code-quality):** Merge consecutive list appends into a single extend ([`merge-list-appends-into-extend`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/merge-list-appends-into-extend/))
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +14 to +21
queue = []
for i in range(numCourses):
if in_degree[i] == 0:
queue.append(i)

count = 0
while queue:
course = queue.pop(0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Using list.pop(0) for the queue leads to O(n²) behavior; a deque would be more efficient.

Because lists shift all elements on pop(0), each dequeue is O(n), making the overall traversal O(n²) for large numCourses. collections.deque.popleft() keeps these queue operations O(1).

Suggested implementation:

from collections import deque

class Solution:

To fully implement the deque-based queue:

  1. Locate the section in canFinish where the queue is created and initialized. It likely looks something like:

    queue = []
    for i in range(numCourses):
        if in_degree[i] == 0:
            queue.append(i)

    Change this to:

    queue = deque()
    for i in range(numCourses):
        if in_degree[i] == 0:
            queue.append(i)

    (append remains the same; only the type changes.)

  2. Locate the loop where elements are dequeued, which should currently look like:

    while queue:
        course = queue.pop(0)
        count += 1
        # ...

    Change the dequeue to use popleft():

    while queue:
        course = queue.popleft()
        count += 1
        # ...

These changes will ensure the BFS/topological sort uses collections.deque with O(1) enqueue/dequeue instead of list pop(0) with O(n) behavior.

Comment on lines +14 to +21
queue = []
for i in range(numCourses):
if in_degree[i] == 0:
queue.append(i)

res = []
while queue:
course = queue.pop(0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): As in canFinish, using pop(0) on a list for the BFS queue is inefficient.

Here queue.pop(0) is O(n) per pop. Using collections.deque and popleft() would make the BFS queue operations O(1), which scales better for large graphs.

Suggested implementation:

        # Find all courses with no prerequisites
        queue = deque()
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        count = 0
        while queue:
            course = queue.popleft()
            count += 1

To fully implement this change, ensure that deque is imported at the top of solutions/210/01.py:

from collections import deque

If there is already an import section, add this import alongside the others.

### Strategy (The "Why")

**1.1 Constraints & Complexity:**
- **Constraints:** We're working with a 32-bit unsigned integer. The input `n` ranges from 0 to 2^31 - 2 and is always even.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Constraints for n (range and "always even") look incorrect for this problem.

The constraint line describes n as 0 to 2^31 - 2 and always even, which doesn’t match a 32-bit unsigned integer or typical bit-reversal specs. Please adjust the upper bound (e.g., 2^31 - 1 or 2^32 - 1, per the intended spec) and drop the “always even” condition unless the problem explicitly requires it.

Comment on lines +6 to +9
- **Constraints:** The input `n` is a positive integer from 1 to 2^31 - 1.
- **Time Complexity:** O(k) where k is the number of set bits (1s) in the binary representation. In worst case, this is O(32) = O(1) for 32-bit integers.
- **Space Complexity:** O(1) - We use only a constant amount of extra space.
- **Edge Case:** If `n = 0`, there are no set bits, so the result is 0.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Constraints and edge-case description are inconsistent regarding whether n = 0 is allowed.

The constraints say n is in [1, 2^31 - 1], but the edge-case section handles n = 0. Please either update the constraints to include 0 or remove/rephrase the n = 0 case so the allowed range and examples align.

Comment on lines +7 to +18

if not directions:
return 0

res = 0
# Count all non-stationary cars in the middle section
# Each R or L in the middle will eventually collide
for char in directions:
if char != 'S':
res += 1

return res
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): We've found these issues:

Suggested change
if not directions:
return 0
res = 0
# Count all non-stationary cars in the middle section
# Each R or L in the middle will eventually collide
for char in directions:
if char != 'S':
res += 1
return res
return 0 if not directions else sum(1 for char in directions if char != 'S')

@romankurnovskii romankurnovskii merged commit e6f5fe7 into main Dec 4, 2025
2 of 3 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (7)
solutions/221/01.py (1)

1-22: LGTM!

Correct DP implementation for the maximal square problem. The recurrence relation dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 is properly applied, and edge cases (empty matrix, boundary cells) are handled correctly.

Optional: Space can be optimized from O(m×n) to O(n) by keeping only the previous row, but the current implementation is clear and maintainable.

solutions/2211/01.py (1)

1-19: LGTM!

Clever solution leveraging the insight that leading 'L's and trailing 'R's never collide. The approach is correct and efficient with O(n) time complexity.

Optional simplification: The loop on lines 14-16 can be replaced with a more Pythonic one-liner:

-        res = 0
-        # Count all non-stationary cars in the middle section
-        # Each R or L in the middle will eventually collide
-        for char in directions:
-            if char != 'S':
-                res += 1
-        
-        return res
+        # Count all non-stationary cars in the middle section
+        return len(directions) - directions.count('S')
explanations/221/en.md (2)

28-35: Specify a language for the example code block

The example matrix is in a fenced block without a language, which markdownlint flags and also misses out on syntax highlighting.

You can mark it as Python-like data:

-Example matrix:
-```
-[["1","0","1","0","0"],
- ["1","0","1","1","1"],
- ["1","1","1","1","1"],
- ["1","0","0","1","0"]]
-```
+Example matrix:
+```python
+[["1", "0", "1", "0", "0"],
+ ["1", "0", "1", "1", "1"],
+ ["1", "1", "1", "1", "1"],
+ ["1", "0", "0", "1", "0"]]
+```

This should clear the fenced-code-language warning and makes the snippet clearer.


44-50: Wrap DP index expressions in backticks to avoid link‑style parsing

The table header row uses values like matrix[i][j] and dp[i-1][j-1] without backticks, which markdownlint interprets as reference links ([j], [j-1]) and warns about missing definitions.

You can both improve readability and silence MD052 by wrapping these in code spans:

-| (i,j) | matrix[i][j] | dp[i-1][j] | dp[i][j-1] | dp[i-1][j-1] | dp[i][j] | res |
+| (i, j) | `matrix[i][j]` | `dp[i-1][j]` | `dp[i][j-1]` | `dp[i-1][j-1]` | `dp[i][j]` | `res` |

(Adjust spacing/format as you prefer; the key point is adding backticks around the index expressions.)

explanations/212/en.md (1)

48-51: Wrap board[i][j] in backticks to avoid markdown reference warnings

The bullet:

If board[i][j] matches a trie root child, start DFS

is likely triggering markdownlint’s “missing reference” warning for [j]. You can fix that and make it clearer by using a code span:

-- For each cell (i, j):
-- - If board[i][j] matches a trie root child, start DFS
+- For each cell (i, j):
+- If `board[i][j]` matches a trie root child, start DFS

(Similarly, you can wrap other indexed expressions in backticks if you want consistent formatting.)

solutions/207/01.py (1)

4-30: Consider using collections.deque for O(1) queue operations.

The topological sort logic is correct. However, queue.pop(0) on a list is O(n), degrading the overall time complexity from O(V+E) to O(V²+E) when processing many courses. For better performance, use collections.deque with popleft().

Apply this diff:

+from collections import deque
+
 class Solution:
     def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
         # Build adjacency list
         graph = [[] for _ in range(numCourses)]
         in_degree = [0] * numCourses
         
         for course, prereq in prerequisites:
             graph[prereq].append(course)
             in_degree[course] += 1
         
         # Find all courses with no prerequisites
-        queue = []
+        queue = deque()
         for i in range(numCourses):
             if in_degree[i] == 0:
                 queue.append(i)
         
         count = 0
         while queue:
-            course = queue.pop(0)
+            course = queue.popleft()
             count += 1
             
             # Reduce in-degree of dependent courses
             for next_course in graph[course]:
                 in_degree[next_course] -= 1
                 if in_degree[next_course] == 0:
                     queue.append(next_course)
         
         return count == numCourses
solutions/210/01.py (1)

4-30: Consider using collections.deque for O(1) queue operations.

The topological sort implementation is correct. However, queue.pop(0) on a list is O(n), which degrades the overall complexity from O(V+E) to O(V²+E). Using collections.deque with popleft() provides O(1) removal.

Apply this diff:

+from collections import deque
+
 class Solution:
     def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
         # Build adjacency list
         graph = [[] for _ in range(numCourses)]
         in_degree = [0] * numCourses
         
         for course, prereq in prerequisites:
             graph[prereq].append(course)
             in_degree[course] += 1
         
         # Find all courses with no prerequisites
-        queue = []
+        queue = deque()
         for i in range(numCourses):
             if in_degree[i] == 0:
                 queue.append(i)
         
         res = []
         while queue:
-            course = queue.pop(0)
+            course = queue.popleft()
             res.append(course)
             
             # Reduce in-degree of dependent courses
             for next_course in graph[course]:
                 in_degree[next_course] -= 1
                 if in_degree[next_course] == 0:
                     queue.append(next_course)
         
         return res if len(res) == numCourses else []
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9ccc4d and bd2bf9d.

📒 Files selected for processing (30)
  • explanations/190/en.md (1 hunks)
  • explanations/191/en.md (1 hunks)
  • explanations/201/en.md (1 hunks)
  • explanations/202/en.md (1 hunks)
  • explanations/207/en.md (1 hunks)
  • explanations/209/en.md (1 hunks)
  • explanations/210/en.md (1 hunks)
  • explanations/211/en.md (1 hunks)
  • explanations/212/en.md (1 hunks)
  • explanations/221/en.md (1 hunks)
  • explanations/2211/en.md (1 hunks)
  • explanations/222/en.md (1 hunks)
  • explanations/224/en.md (1 hunks)
  • explanations/226/en.md (1 hunks)
  • explanations/295/en.md (1 hunks)
  • solutions/190/01.py (1 hunks)
  • solutions/191/01.py (1 hunks)
  • solutions/201/01.py (1 hunks)
  • solutions/202/01.py (1 hunks)
  • solutions/207/01.py (1 hunks)
  • solutions/209/01.py (1 hunks)
  • solutions/210/01.py (1 hunks)
  • solutions/211/01.py (1 hunks)
  • solutions/212/01.py (1 hunks)
  • solutions/221/01.py (1 hunks)
  • solutions/2211/01.py (1 hunks)
  • solutions/222/01.py (1 hunks)
  • solutions/224/01.py (1 hunks)
  • solutions/226/01.py (1 hunks)
  • solutions/295/01.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
solutions/190/01.py (2)
solutions/191/01.py (1)
  • Solution (1-8)
solutions/201/01.py (1)
  • Solution (1-10)
solutions/207/01.py (1)
solutions/210/01.py (1)
  • Solution (3-30)
solutions/210/01.py (1)
solutions/207/01.py (1)
  • Solution (3-30)
solutions/212/01.py (1)
solutions/211/01.py (2)
  • TrieNode (1-4)
  • dfs (19-32)
solutions/211/01.py (1)
solutions/212/01.py (2)
  • TrieNode (1-4)
  • dfs (23-47)
🪛 LanguageTool
explanations/209/en.md

[grammar] ~12-~12: Use a hyphen to join words.
Context: ...roach:** The goal is to find the minimal length subarray whose sum is at least `t...

(QB_NEW_EN_HYPHEN)

explanations/201/en.md

[style] ~15-~15: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...where n is the range size, which can be very large. - Optimized Strategy: Find the com...

(EN_WEAK_ADJECTIVE)

explanations/224/en.md

[style] ~23-~23: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...sign, reset number, and update sign. 4. For '(', push current result and sign to st...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ign to stack, reset result and sign. 5. For ')', add current number to result, then...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 markdownlint-cli2 (0.18.1)
explanations/212/en.md

7-7: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


7-7: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


15-15: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


15-15: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


49-49: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)

explanations/221/en.md

15-15: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


15-15: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


30-30: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


44-44: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)


44-44: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)


44-44: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)


44-44: Reference links and images should use a label that is defined
Missing link or image reference definition: "j-1"

(MD052, reference-links-images)


44-44: Reference links and images should use a label that is defined
Missing link or image reference definition: "j-1"

(MD052, reference-links-images)

explanations/211/en.md

31-31: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff (0.14.7)
solutions/222/01.py

11-11: Undefined name TreeNode

(F821)

solutions/226/01.py

11-11: Undefined name TreeNode

(F821)


11-11: Undefined name TreeNode

(F821)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (19)
explanations/226/en.md (1)

1-66: LGTM!

The explanation is well-structured with clear complexity analysis, decomposition steps, and a helpful trace walkthrough table. The visual representation of the tree before and after inversion aids understanding.

solutions/191/01.py (1)

1-9: LGTM!

Clean implementation of Brian Kernighan's algorithm. The n &= n - 1 trick efficiently clears the rightmost set bit, making this O(k) where k is the number of set bits—optimal for this problem.

solutions/190/01.py (1)

1-10: LGTM!

Correct bit-reversal implementation. The approach of extracting each bit at position i and placing it at position 31 - i is clear and efficient. O(32) = O(1) time complexity.

explanations/191/en.md (1)

5-50: Explanation aligns well with the implemented algorithm

Constraints, complexity (O(k) with k set bits), and the n & (n - 1) walkthrough are accurate and match the typical solution. Nothing to change here.

explanations/224/en.md (1)

19-60: Calculator walkthrough and stack logic look solid

The decomposition and the trace for (1+(4+5+2)-3)+(6+8) correctly reflect the standard single-pass stack solution. The description of pushing [res, sign] on '(' and combining on ')' matches the usual implementation.

solutions/201/01.py (1)

1-10: Range AND implementation is correct and idiomatic

Using common-prefix via right shifts and then shifting back (left << shift) is the canonical O(1) solution for this problem; the loop condition and state updates are all correct.

explanations/2211/en.md (1)

5-51: Collision-counting explanation matches the optimized approach

Trimming escaping L/R cars and then counting non‑'S' cars in the middle is exactly the intended O(n) strategy, and the "RLRSLL" walkthrough is consistent with the final answer of 5.

solutions/224/01.py (1)

1-30: Calculator implementation looks correct and complete.

Stack handling, sign management, and digit accumulation all align with the standard solution for LeetCode 224, including nested parentheses and unary +/- cases. No changes needed.

solutions/295/01.py (1)

1-27: Two‑heap median structure is correctly implemented.

Heap partitioning, rebalancing, and median calculation are all consistent with the canonical O(log n) / O(1) approach for LeetCode 295. No adjustments needed.

solutions/212/01.py (1)

1-55: Trie + DFS solution for Word Search II is sound and efficient.

Trie construction, DFS traversal with in‑place marking, de‑duplication via curr_node.word = None, and leaf pruning are all correctly wired and match the standard optimized pattern for LeetCode 212. Looks good.

explanations/201/en.md (1)

5-49: Range AND explanation correctly matches the standard common-prefix solution.

The description of shifting left and right until they match, tracking shift, and then left-shifting back is accurate and well-aligned with the typical O(log n) implementation for LeetCode 201. No changes needed.

solutions/211/01.py (1)

1-35: Trie-based WordDictionary implementation is correct.

addWord and DFS-based search (with '.' wildcard support) follow the standard LeetCode 211 pattern and correctly handle branching and termination conditions. Looks good as-is.

solutions/222/01.py (1)

11-31: LGTM! Efficient complete binary tree node counting.

The implementation correctly leverages the complete binary tree property by comparing left and right subtree heights to determine which subtree is full, then recursively counting only the incomplete subtree. The bit-shift operation efficiently calculates 2^height.

solutions/202/01.py (1)

2-18: LGTM! Clean happy number implementation.

The cycle detection using a set is correct, and the digit sum-of-squares calculation is properly implemented. The algorithm correctly identifies happy numbers by detecting either convergence to 1 or a cycle.

solutions/209/01.py (1)

4-17: LGTM! Correct sliding window implementation.

The two-pointer sliding window approach efficiently finds the minimal subarray length with sum ≥ target in O(n) time. The logic correctly expands the window rightward and contracts leftward while maintaining the minimum length.

explanations/209/en.md (1)

1-56: LGTM! Comprehensive documentation.

The explanation thoroughly covers the sliding window strategy with clear complexity analysis, edge cases, and a detailed step-by-step walkthrough. The structure aligns well with the repository's documentation format.

explanations/202/en.md (1)

1-53: LGTM! Clear and thorough explanation.

The documentation effectively explains the happy number algorithm with proper coverage of cycle detection, complexity analysis, and a detailed walkthrough. The structure is consistent with the repository's documentation standards.

explanations/207/en.md (1)

1-54: LGTM! Well-structured explanation of topological sorting.

The documentation clearly explains Kahn's algorithm for cycle detection in course prerequisites, with proper complexity analysis and a step-by-step example. The structure follows the repository's documentation format effectively.

explanations/210/en.md (1)

1-55: Comprehensive and accurate explanation of Kahn's algorithm for topological sorting.

The explanation is well-structured, technically correct, and pedagogically clear. The strategy section effectively contrasts brute force vs. optimized approaches, the complexity analysis is accurate (O(V+E) time and space), and the step-by-step trace table with the concrete example [0,1,2,3] is excellent for understanding the algorithm flow. The in-degree calculations and graph construction are correct given the prerequisite format [course, prerequisite].

The format follows the stated repository structure (strategy, complexity, examples, walkthrough).

Optional suggestion for polish: Consider adding a brief note at the very beginning mentioning the problem context (e.g., "Find a valid course ordering given prerequisites, or detect cycles") to help readers immediately understand what problem we're solving before diving into the algorithm.

Comment on lines +5 to +8
**1.1 Constraints & Complexity:**
- **Constraints:** We're working with a 32-bit unsigned integer. The input `n` ranges from 0 to 2^31 - 2 and is always even.
- **Time Complexity:** O(1) - We iterate exactly 32 times regardless of input size.
- **Space Complexity:** O(1) - We use only a constant amount of extra space.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the constraints description (incorrect range and “always even”).

The line

The input n ranges from 0 to 2^31 - 2 and is always even.

doesn’t match the actual problem: the input is just a 32‑bit unsigned integer; it is not guaranteed to be even, and the upper bound here is off. Suggest rephrasing to something like:

Constraints: We’re working with a 32‑bit unsigned integer n (i.e., 0 <= n < 2^32).

This keeps the explanation accurate without over‑constraining the input.

🤖 Prompt for AI Agents
In explanations/190/en.md around lines 5 to 8, the constraints sentence
incorrectly states the input range and that n is always even; update it to
correctly describe the input as a 32-bit unsigned integer with range 0 <= n <
2^32 and remove any claim that n is always even (or otherwise state parity is
unconstrained), keeping the Time and Space Complexity lines unchanged.

Comment on lines +5 to +10
**1.1 Constraints & Complexity:**
- **Constraints:** Word length is 1 to 25, and there are at most 10^4 calls to `addWord` and `search`. Search queries have at most 2 dots.
- **Time Complexity:**
- `addWord`: O(m) where m is the word length
- `search`: O(m * 26^k) in worst case where k is the number of dots, but typically much better
- **Space Complexity:** O(N * M) where N is the number of words and M is the average word length.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify search constraints ('.' is not limited to 2 occurrences)

The line:

Search queries have at most 2 dots.

is misleading for this problem; the search pattern can contain '.' in any positions up to the word length, and the algorithm/complexity discussion already uses a generic k = number of dots.

I’d suggest generalizing the constraints:

- **Constraints:** Word length is 1 to 25, and there are at most 10^4 calls to `addWord` and `search`. Search queries have at most 2 dots.
+ **Constraints:** Word length is 1 to 25, and there are at most 10^4 calls to `addWord` and `search`. Search queries may contain the `'.'` wildcard in any positions.

This keeps the explanation accurate without over-restricting the problem statement.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**1.1 Constraints & Complexity:**
- **Constraints:** Word length is 1 to 25, and there are at most 10^4 calls to `addWord` and `search`. Search queries have at most 2 dots.
- **Time Complexity:**
- `addWord`: O(m) where m is the word length
- `search`: O(m * 26^k) in worst case where k is the number of dots, but typically much better
- **Space Complexity:** O(N * M) where N is the number of words and M is the average word length.
**1.1 Constraints & Complexity:**
- **Constraints:** Word length is 1 to 25, and there are at most 10^4 calls to `addWord` and `search`. Search queries may contain the `'.'` wildcard in any positions.
- **Time Complexity:**
- `addWord`: O(m) where m is the word length
- `search`: O(m * 26^k) in worst case where k is the number of dots, but typically much better
- **Space Complexity:** O(N * M) where N is the number of words and M is the average word length.
🤖 Prompt for AI Agents
explanations/211/en.md around lines 5 to 10: the current text incorrectly states
"Search queries have at most 2 dots." Update this to remove the hard cap and
instead state that search patterns may contain dots in any positions up to the
word length (e.g., "Search queries may contain '.' in any positions up to the
word length; let k be the number of dots") and ensure the Time Complexity
paragraph references k as the number of dots to match the rest of the section.

Comment on lines +28 to +52
**2.1 Initialization & Example Setup:**
Example tree: `[1,2,3,4,5,6]` (complete binary tree with 6 nodes)

Root = 1, left = 2, right = 3

**2.2 Start Checking:**
Calculate left height from root.left (node 2): follow left children → 4 → None, height = 2
Calculate right height from root.right (node 3): follow left children → None, height = 0

**2.3 Trace Walkthrough:**

| Node | Left Height | Right Height | Action |
|------|-------------|---------------|--------|
| 1 | 2 | 0 | Heights differ, right is full. Count = 2^0 + countNodes(left) |
| 2 | 1 | 0 | Heights differ, right is full. Count = 2^0 + countNodes(left) |
| 4 | 0 | 0 | Heights equal, left is full. Count = 2^0 + countNodes(right) |
| 5 | 0 | 0 | Base case, return 1 |

**2.4 Increment and Loop:**
Recursively:
- If left_height == right_height: return (1 << left_height) + countNodes(right)
- Else: return (1 << right_height) + countNodes(left)

**2.5 Return Result:**
Total count = 1 (root) + 1 (node 2) + 1 (node 4) + 1 (node 5) + 1 (node 3) + 1 (node 6) = 6 nodes.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align the walkthrough heights/actions with the described algorithm.

In the example with tree [1,2,3,4,5,6], the stated heights and actions in the walkthrough are inconsistent with a complete-tree structure and with the earlier description:

  • Line 35–36 describe the right height from root.right as going directly to None with height 0, which doesn’t match a tree where node 3 has a left child 6.
  • The table row for node 1 (and subsequent rows) then apply formulas based on these mismatched heights.

The high-level algorithm you describe (using subtree heights to decide which side is full and recursing on the other) is correct, but the concrete numbers in this trace should be recomputed so that:

  • Left/right heights reflect the actual example tree structure and the height function you intend to use.
  • The “Action” column corresponds to the real branch (left_height == right_height vs. not) taken at each node.

Updating the table to show a consistent run of the algorithm will make the explanation much clearer.

Comment on lines +52 to +55
After adding 1, 2, 3:
- `max_heap = [-2, -1]`, `min_heap = [3]`
- Median = (-(-2) + 3) / 2 = (2 + 3) / 2 = 2.5 (if equal sizes)
- Or median = -(-2) = 2 (if max_heap is larger)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix median example for the two‑heap walkthrough

For the example after adding 1, 2, 3, the median is 2, not 2.5. The current bullets mix the odd-length example with the even-length formula, which is confusing.

Consider updating this section to clearly distinguish odd vs even counts, e.g.:

-After adding 1, 2, 3:
-- `max_heap = [-2, -1]`, `min_heap = [3]`
-- Median = (-(-2) + 3) / 2 = (2 + 3) / 2 = 2.5 (if equal sizes)
-- Or median = -(-2) = 2 (if max_heap is larger)
+After adding 1, 2, 3:
+- `max_heap = [-2, -1]`, `min_heap = [3]`
+- We have an odd number of elements, so the median is the top of the larger heap: `-(-2) = 2`.
+
+For an even number of elements (e.g., `[1, 2, 3, 4]` with
+`max_heap = [-2, -1]` and `min_heap = [3, 4]`), the median is
+the average of both tops: `(2 + 3) / 2 = 2.5`.

This keeps both behaviors clear and consistent with the example data.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
After adding 1, 2, 3:
- `max_heap = [-2, -1]`, `min_heap = [3]`
- Median = (-(-2) + 3) / 2 = (2 + 3) / 2 = 2.5 (if equal sizes)
- Or median = -(-2) = 2 (if max_heap is larger)
After adding 1, 2, 3:
- `max_heap = [-2, -1]`, `min_heap = [3]`
- We have an odd number of elements, so the median is the top of the larger heap: `-(-2) = 2`.
For an even number of elements (e.g., `[1, 2, 3, 4]` with
`max_heap = [-2, -1]` and `min_heap = [3, 4]`), the median is
the average of both tops: `(2 + 3) / 2 = 2.5`.
🤖 Prompt for AI Agents
In explanations/295/en.md around lines 52 to 55, the median example after adding
1, 2, 3 incorrectly shows 2.5 by mixing the even-length formula with an
odd-length state; update the bullets to state the heap contents and then clearly
show the odd-count median rule: max_heap = [-2, -1], min_heap = [3], median =
top of max_heap => -(-2) = 2; separately add a brief note demonstrating the
even-count case (when heaps are equal size) where median = (top_max + top_min)/2
to avoid confusion.

Comment on lines 13 to 22
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None

root.left, root.right = root.right, root.left

invertTree(root.left)
invertTree(root.right)

return root
# Swap left and right children
root.left, root.right = root.right, root.left

# Recursively invert subtrees
self.invertTree(root.left)
self.invertTree(root.right)

return root
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix undefined TreeNode in type hints (runtime NameError).

TreeNode is only present in a commented stub, but used in annotations:

def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:

Without a real TreeNode definition or string/“future” annotations, this will raise a NameError when the function is defined.

A minimal fix that keeps the LeetCode-style commented stub but makes the file valid Python is to use forward-referenced string annotations:

-from typing import Optional
+from typing import Optional

 class Solution:
-    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
+    def invertTree(self, root: Optional["TreeNode"]) -> Optional["TreeNode"]:

Alternatively, you could add from __future__ import annotations at the top, but using quoted "TreeNode" is enough here.

🧰 Tools
🪛 Ruff (0.14.7)

11-11: Undefined name TreeNode

(F821)


11-11: Undefined name TreeNode

(F821)

🤖 Prompt for AI Agents
In solutions/226/01.py around lines 10 to 22 the type hints use TreeNode which
is not defined at runtime causing a NameError; update the annotations to use
forward-referenced string types (e.g. "TreeNode") or add from __future__ import
annotations at the top of the file so the annotations are not evaluated at
function definition time, then run a quick lint/type check to ensure no other
undefined names remain.

@romankurnovskii romankurnovskii deleted the problems-2211-190-191-201-202-207-209-210-211-212-221-222-224-226-295 branch December 4, 2025 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants