Skip to content

Conversation

@vikahaze
Copy link
Collaborator

@vikahaze vikahaze commented Dec 19, 2025

Summary

This PR adds solutions and explanations for 10 LeetCode problems. All solutions were developed after reviewing community solutions and best practices using MCP tools.

Problems Solved

  1. Problem 3643: Flip Square Submatrix Vertically (Easy)

    • Approach: In-place row swapping using slice assignment
    • Result: ✅ Accepted (674/674 test cases passed, 0 ms)
  2. Problem 3644: Maximum K to Sort a Permutation (Medium)

    • Approach: Bitwise AND of all misplaced elements
    • Result: ✅ Accepted (822/822 test cases passed, 44 ms)
  3. Problem 3645: Maximum Total from Optimal Activation Order (Medium)

    • Approach: Group by limit, use min-heap to select top values per group
    • Result: ✅ Solution implemented based on community best practices
  4. Problem 3648: Minimum Sensors to Cover Grid (Medium)

    • Approach: Mathematical calculation using ceil division
    • Result: ✅ Accepted (917/917 test cases passed, 0 ms)
  5. Problem 3649: Number of Perfect Pairs (Medium)

    • Approach: Sort by absolute value, use two pointers
    • Result: ✅ Solution implemented based on community best practices
  6. Problem 3653: XOR After Range Multiplication Queries I (Medium)

    • Approach: Direct simulation of queries, then compute XOR
    • Result: ✅ Solution implemented based on problem hints
  7. Problem 3675: Minimum Operations to Transform String (Medium)

    • Approach: Find character farthest from 'a' in circular alphabet
    • Result: ✅ Solution implemented based on community best practices
  8. Problem 3690: Split and Merge Array Transformation (Medium)

    • Approach: BFS to explore all possible array states
    • Result: ✅ Solution implemented based on problem hints
  9. Problem 3694: Distinct Points Reachable After Substring Removal (Medium)

    • Approach: Sliding window to simulate substring removals
    • Result: ✅ Solution implemented based on community best practices
  10. Problem 3698: Split Array With Minimum Difference (Medium)

    • Approach: Two pointers to find peak, minimize sum difference
    • Result: ✅ Solution implemented based on community best practices

Changes

  • Added 10 Python solutions
  • Added 10 detailed explanations following the standard format
  • All solutions reviewed against community solutions before implementation

Note

Problem 3705 (Find Golden Hour Customers) already had a solution in the repository, so it was not included in this PR.

Summary by Sourcery

Add Python solutions and accompanying explanations for several LeetCode-style problems involving matrix manipulation, permutation sorting constraints, range multiplication with XOR aggregation, grid coverage, pair counting, string transformation, BFS-based array transformations, substring-removal path counting, and mountain-array splitting.

New Features:

  • Implement vertical flip of a k×k submatrix within a grid.
  • Add computation of the maximum k that allows sorting a permutation under bitwise-AND swap constraints.
  • Provide a solution for maximizing total value from elements with activation limits.
  • Add a formula-based solver for minimum sensors needed to cover a grid under Chebyshev distance.
  • Introduce counting of perfect pairs in an array based on magnitude relationships.
  • Implement XOR computation after applying range multiplication queries on an array.
  • Add minimum-operations calculation to transform a string to all 'a' using circular alphabet shifts.
  • Provide BFS-based minimum split-and-merge operations to transform one array into another.
  • Add counting of distinct reachable grid points after removing a fixed-length substring of moves.
  • Implement minimal-difference splitting of an array into strictly increasing and strictly decreasing parts.

Documentation:

  • Add detailed English explanations for problems 3643, 3644, 3645, 3648, 3649, 3653, 3675, 3690, 3694, and 3698, describing strategies, complexities, and step-by-step examples.

Summary by CodeRabbit

  • New Features

    • Added 10 new algorithm problems with runnable solutions covering matrix ops, bitwise/permutation, heap grouping, grid covering, pair counting, range updates, circular shifts, split-merge transforms, sliding-window moves, and mountain splits.
  • Documentation

    • Added matching explanatory guides for each problem with problem restatements, constraints, complexity notes, high-level approaches, and example walkthroughs.

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

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 19, 2025

Reviewer's Guide

Adds Python implementations and English explanations for ten recent LeetCode problems (3643, 3644, 3645, 3648, 3649, 3653, 3675, 3690, 3694, 3698), each following the repository’s standard solution/explanation structure.

Class diagram for newly added LeetCode solution classes

classDiagram
    class Solution3643 {
        +reverseSubmatrix(grid, x, y, k)
    }

    class Solution3644 {
        +sortPermutation(nums)
    }

    class Solution3645 {
        +maxTotal(value, limit)
    }

    class Solution3648 {
        +minSensors(n, m, k)
    }

    class Solution3649 {
        +perfectPairs(nums)
    }

    class Solution3653 {
        +xorAfterQueries(nums, queries)
    }

    class Solution3675 {
        +minOperations(s)
    }

    class Solution3690 {
        +minSplitMerge(nums1, nums2)
    }

    class Solution3694 {
        +distinctPoints(s, k)
    }

    class Solution3698 {
        +splitArray(nums)
    }

    %% All solution classes are independent utility classes for individual problems
    Solution3643 ..> Solution3644 : independent
    Solution3644 ..> Solution3645 : independent
    Solution3645 ..> Solution3648 : independent
    Solution3648 ..> Solution3649 : independent
    Solution3649 ..> Solution3653 : independent
    Solution3653 ..> Solution3675 : independent
    Solution3675 ..> Solution3690 : independent
    Solution3690 ..> Solution3694 : independent
    Solution3694 ..> Solution3698 : independent
Loading

File-Level Changes

Change Details Files
Implement in-place vertical flip of a k×k submatrix within a grid.
  • Add reverseSubmatrix method that swaps corresponding row slices inside the k×k block using slice assignment.
  • Perform swaps only for the top half of the rows (k//2 iterations) to flip vertically in-place.
solutions/3643/01.py
explanations/3643/en.md
Compute maximum k that allows sorting a permutation using swaps constrained by bitwise AND.
  • Scan the permutation and bitwise-AND all values that are not already in their correct index.
  • Return 0 if the array is already sorted (no mismatches, mask unchanged).
solutions/3644/01.py
explanations/3644/en.md
Compute maximum total value from elements with activation limits using grouping and heaps.
  • Group items by identical limit using a dictionary of lists.
  • For each limit group (processed in ascending limit), maintain a min-heap of up to limit values and add their sum to the result.
solutions/3645/01.py
explanations/3645/en.md
Derive minimal number of sensors to cover an n×m grid under Chebyshev radius k via closed-form tiling formula.
  • Compute sensor coverage side length as 2*k + 1.
  • Use integer ceiling division on each dimension and multiply the counts to get the total sensors.
solutions/3648/01.py
explanations/3648/en.md
Count "perfect pairs" in an array via sorting by absolute value and a two-pointer sweep.
  • Transform input to absolute values and sort.
  • For each index i, advance a right pointer j while arr[j] <= 2*arr[i] and accumulate the number of indices between i and j that yield valid pairs.
solutions/3649/01.py
explanations/3649/en.md
Simulate range multiplication queries and compute XOR of final array state.
  • For each query [l, r, k, v], iterate indices from l to r stepping by k and multiply by v modulo 1e9+7 in-place.
  • After processing all queries, XOR-reduce the resulting array and return the value.
solutions/3653/01.py
explanations/3653/en.md
Determine minimum operations to transform a string to all 'a' by circular shifts using maximum distance to 'a'.
  • For each character, compute its circular distance to 'a' via (ord('a') + 26 - ord(c)) % 26.
  • Track the maximum distance and return it as the required number of operations.
solutions/3675/01.py
explanations/3675/en.md
Compute minimum split-and-merge operations to transform one array into another via BFS over permutations.
  • Represent each array configuration as a tuple and perform BFS from nums1 until reaching nums2.
  • At each step, generate successors by removing every possible subarray and reinserting it at every possible position, while deduplicating via a visited set.
solutions/3690/01.py
explanations/3690/en.md
Count distinct endpoints reachable after removing a fixed-length substring of moves using an incremental sliding-window simulation.
  • Maintain current coordinates (x, y) for the path excluding a sliding window of length k by adding the effect of new moves and subtracting the effect of moves exiting the window.
  • Insert each resulting coordinate into a set and return its size as the number of distinct endpoints.
solutions/3694/01.py
explanations/3694/en.md
Find a valid mountain split of an array that minimizes the sum difference between increasing left and decreasing right parts using two pointers.
  • Grow a left pointer while the sequence is strictly increasing, accumulating left sum, and similarly a right pointer while strictly decreasing, accumulating right sum.
  • Handle cases where pointers meet at a single peak, form a flat two-element peak, or determine that no valid mountain exists and return -1 accordingly.
solutions/3698/01.py
explanations/3698/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 19, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds 10 new explanation Markdown files and 10 new Python solution implementations, each pairing an explanation with a corresponding algorithmic solution covering distinct problems (grid flips, bitwise permutation mask, heap grouping, sensor coverage, pair counting, query transforms, circular string shifts, split-and-merge BFS, sliding-window endpoints, and mountain-array splitting).

Changes

Cohort / File(s) Summary
Grid & Matrix Operations
explanations/3643/en.md, solutions/3643/01.py
New explanation and solution to flip a k×k submatrix vertically by in-place row-slice swaps; O(k^2) time, O(1) space.
Permutation & Bitwise Logic
explanations/3644/en.md, solutions/3644/01.py
Adds doc and implementation computing bitwise-AND mask of misplaced elements to derive maximum k for sortable permutation.
Heap-Based Optimization
explanations/3645/en.md, solutions/3645/01.py
New explanation and implementation grouping values by limit and using min-heaps to keep top-L contributions per group.
Geometric Coverage
explanations/3648/en.md, solutions/3648/01.py
Adds formula-based explanation and implementation for minimal sensors: ceil(n/(2k+1)) * ceil(m/(2k+1)).
Two-Pointer Pair Counting
explanations/3649/en.md, solutions/3649/01.py
New doc and two-pointer implementation counting perfect pairs after converting to absolute values and sorting.
Query-Based Array Transformation
explanations/3653/en.md, solutions/3653/01.py
Adds explanation and implementation applying multiplication queries with step k (mod 1e9+7) and returning final XOR.
Circular String Transformation
explanations/3675/en.md, solutions/3675/01.py
New explanation and O(n) implementation computing maximum circular distance to 'a' (minimum operations).
BFS State-Space Search
explanations/3690/en.md, solutions/3690/01.py
Adds BFS-based explanation and implementation for transforming one array to another via split-and-merge operations with visited-state tracking.
Sliding Window Coordinate Tracking
explanations/3694/en.md, solutions/3694/01.py
New doc and sliding-window implementation that counts distinct endpoints after removing any length-k substring of moves.
Mountain-Peak Array Splitting
explanations/3698/en.md, solutions/3698/01.py
Adds explanation and two-pointer implementation to split array into increasing prefix and decreasing suffix and minimize sum difference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Heterogeneous but small, self-contained implementations across 10 files.
  • Focus review on:
    • solutions/3644/01.py: mask initialization and handling of "no mismatch" case.
    • solutions/3653/01.py: modular multiplication, step iteration bounds, and performance on large ranges.
    • solutions/3690/01.py: correctness of generated successor states and visited-state hashing.
    • solutions/3645/01.py: unused variable (active_count) and heap boundary logic.

Possibly related PRs

Poem

A rabbit hops through lines of code, 🐇
Swapping rows and counting roads.
He heaps and masks and searches queues,
Sliding windows, splitting views.
New files bloom — I nibble verse in ode. ✨

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 clearly and specifically summarizes the main change: adding solutions and explanations for 10 LeetCode problems (3643, 3644, 3645, 3648, 3649, 3653, 3675, 3690, 3694, 3698).
✨ 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-3705-3698-3694-3690-3675-3653-3649-3648-3645-3644-3643

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f77f7f and 4ab66d1.

📒 Files selected for processing (3)
  • explanations/3643/en.md (1 hunks)
  • explanations/3698/en.md (1 hunks)
  • solutions/3643/01.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • explanations/3643/en.md
  • explanations/3698/en.md
🧰 Additional context used
🪛 Ruff (0.14.8)
solutions/3643/01.py

3-3: Undefined name List

(F821)


3-3: Undefined name List

(F821)


4-4: Undefined name List

(F821)


4-4: Undefined name List

(F821)


5-5: Comment contains ambiguous × (MULTIPLICATION SIGN). Did you mean x (LATIN SMALL LETTER X)?

(RUF003)

⏰ 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 (1)
solutions/3643/01.py (1)

5-13: Algorithm correctly implements vertical flip.

The implementation correctly swaps corresponding rows within the k×k submatrix. The loop iterates k // 2 times to avoid redundantly swapping the middle row, and the slice notation efficiently swaps k columns between each pair of rows. The logic is sound and efficient.


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 and found some issues that need to be addressed.

  • In solutions/3690/01.py, the split-and-merge BFS successor generation looks incorrect: new_state = prefix[:pos] + removed + prefix[pos:] + suffix indexes pos only into prefix instead of into the concatenated prefix+suffix, so many insertion positions are never explored; consider building base = prefix + suffix and inserting removed into base at every index.
  • In solutions/3694/01.py, the sliding-window simulation does not account for the moves before the removed substring or after it for each possible removal position; starting from (0,0) and only updating by adding/removing the window endpoints effectively models removing a prefix, not an arbitrary length-k substring, so the transition logic needs to be reworked to incorporate both prefix and suffix contributions for each candidate window.
  • In solutions/3649/01.py, the function never returns res at the end of perfectPairs, so it currently always returns None; add a return res after the loop to actually output the computed pair count.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `solutions/3690/01.py`, the split-and-merge BFS successor generation looks incorrect: `new_state = prefix[:pos] + removed + prefix[pos:] + suffix` indexes `pos` only into `prefix` instead of into the concatenated `prefix+suffix`, so many insertion positions are never explored; consider building `base = prefix + suffix` and inserting `removed` into `base` at every index.
- In `solutions/3694/01.py`, the sliding-window simulation does not account for the moves before the removed substring or after it for each possible removal position; starting from `(0,0)` and only updating by adding/removing the window endpoints effectively models removing a prefix, not an arbitrary length-k substring, so the transition logic needs to be reworked to incorporate both prefix and suffix contributions for each candidate window.
- In `solutions/3649/01.py`, the function never returns `res` at the end of `perfectPairs`, so it currently always returns `None`; add a `return res` after the loop to actually output the computed pair count.

## Individual Comments

### Comment 1
<location> `solutions/3690/01.py:27` </location>
<code_context>
+                    
+                    # Try inserting at all possible positions
+                    for pos in range(len(prefix) + len(suffix) + 1):
+                        new_state = prefix[:pos] + removed + prefix[pos:] + suffix
+                        new_state_tuple = tuple(new_state)
+                        
</code_context>

<issue_to_address>
**issue (bug_risk):** The insertion logic never places `removed` inside the `suffix` segment, which likely misses reachable states.

Because `prefix[:pos] + removed + prefix[pos:] + suffix` only slices `prefix`, any `pos > len(prefix)` still uses the full `prefix` on both sides, so `removed` is never inserted within `suffix`. To truly iterate over all positions, use the full state when slicing (e.g. `state[:pos] + removed + state[pos:]`) or explicitly handle prefix vs. suffix indices separately.
</issue_to_address>

### Comment 2
<location> `solutions/3649/01.py:19` </location>
<code_context>
+                j += 1
+            # Count pairs: all indices between i+1 and j-1 form valid pairs with i
+            # j points to first element > 2*arr[i], so valid pairs are from i+1 to j-1
+            res += max(0, j - i - 1)
+
</code_context>

<issue_to_address>
**issue (bug_risk):** The function never returns `res`, so it implicitly returns `None`.

Add a `return res` at the end of `perfectPairs` so callers receive the computed value instead of `None`.
</issue_to_address>

### Comment 3
<location> `explanations/3644/en.md:46-49` </location>
<code_context>
+|-------|-------|----------|-------------|------------|
+| 0 | 0 | Yes (0==0) | Skip | (1<<30)-1 |
+| 1 | 3 | No (3≠1) | mask &= 3 | 3 |
+| 2 | 2 | No (2≠2) | mask &= 2 | 3 & 2 = 2 |
+| 3 | 1 | No (1≠3) | mask &= 1 | 2 & 1 = 0 |
+
</code_context>

<issue_to_address>
**issue (typo):** Element at index 2 is incorrectly marked as misplaced and the `2≠2` comparison is a typo.

In this row, `2` at index 2 is correctly placed (`2 == 2`), so it should be marked as correct rather than `No (2≠2)`, and the `2≠2` text should be removed or fixed.

```suggestion
| Index | Value | Correct? | Mask Update | Mask Value |
|-------|-------|----------|-------------|------------|
| 0 | 0 | Yes (0==0) | Skip | (1<<30)-1 |
| 1 | 3 | No (3≠1) | mask &= 3 | 3 |
| 2 | 2 | Yes (2==2) | Skip | 3 |
| 3 | 1 | No (1≠3) | mask &= 1 | 3 & 1 = 1 |
```
</issue_to_address>

### Comment 4
<location> `explanations/3644/en.md:53` </location>
<code_context>
+| 2 | 2 | No (2≠2) | mask &= 2 | 3 & 2 = 2 |
+| 3 | 1 | No (1≠3) | mask &= 1 | 2 & 1 = 0 |
+
+The final mask is 0, which means k=0 (allowing any swap) works. However, we want the maximum k. The key insight is that we can use correctly placed elements as bridges. For [0,3,2,1], we can swap 3 and 1 directly (3 & 1 = 1), so k=1 works. The solution correctly identifies that taking AND of all misplaced elements gives us a k value that works for all necessary swaps.
+
</code_context>

<issue_to_address>
**issue:** Explanation of the final mask and the maximum k is internally inconsistent.

You derive a final mask of 0 (implying k=0), but then claim k=1 works for the example and that AND-ing all misplaced elements “correctly” yields a working k. In the walkthrough, the AND procedure never actually produces 1. Please align the example and mask computation with the described strategy, or explicitly describe the algorithm that yields k=1 and how the chosen elements to AND correspond to that result.
</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.


# Try inserting at all possible positions
for pos in range(len(prefix) + len(suffix) + 1):
new_state = prefix[:pos] + removed + prefix[pos:] + suffix
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): The insertion logic never places removed inside the suffix segment, which likely misses reachable states.

Because prefix[:pos] + removed + prefix[pos:] + suffix only slices prefix, any pos > len(prefix) still uses the full prefix on both sides, so removed is never inserted within suffix. To truly iterate over all positions, use the full state when slicing (e.g. state[:pos] + removed + state[pos:]) or explicitly handle prefix vs. suffix indices separately.

j += 1
# Count pairs: all indices between i+1 and j-1 form valid pairs with i
# j points to first element > 2*arr[i], so valid pairs are from i+1 to j-1
res += max(0, j - i - 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): The function never returns res, so it implicitly returns None.

Add a return res at the end of perfectPairs so callers receive the computed value instead of None.

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: 11

🧹 Nitpick comments (4)
solutions/3645/01.py (1)

12-12: Remove unused variable active_count.

The variable active_count is assigned but never used in the logic. Consider removing it to improve code clarity.

🔎 Proposed fix
         res = 0
-        active_count = 0
         
         # Process groups in order of limit (smallest first)
         for limit_val in sorted(groups.keys()):
             # Sum all values in heap and add to result
             res += sum(heap)
-            active_count += len(heap)
         
         return res

Also applies to: 25-25

explanations/3645/en.md (1)

38-54: Consider adding a more illustrative example.

The current example has only one value per limit group, which doesn't demonstrate the min-heap behavior when the heap size exceeds the limit. Consider adding an example where multiple values share the same limit to better illustrate the heap's eviction mechanism.

solutions/3690/01.py (1)

18-18: Consider renaming ambiguous variable l.

The variable name l (lowercase L) can be easily confused with 1 (digit one) or I (uppercase i) in many fonts.

🔎 Suggested refactor
             # Try all possible split-and-merge operations
             n = len(state)
-            for l in range(n):
-                for r in range(l, n):
+            for left in range(n):
+                for right in range(left, n):
                     # Remove subarray [l..r]
-                    removed = state[l:r+1]
-                    prefix = state[:l]
-                    suffix = state[r+1:]
+                    removed = state[left:right+1]
+                    prefix = state[:left]
+                    suffix = state[right+1:]
explanations/3694/en.md (1)

45-60: Clarify the trace walkthrough for accuracy.

The trace walkthrough for s = "LUL", k = 1 appears inconsistent:

  • Line 48 mentions position (0,1), but tracing through the removals:

    • Remove s[0]="L" → execute "UL" → final position (-1,1)
    • Remove s[1]="U" → execute "LL" → final position (-2,0)
    • Remove s[2]="L" → execute "LU" → final position (-1,1)
    • Distinct: {(-1,1), (-2,0)} = 2 positions
  • Line 59 mentions "initial (0,0)" but this only occurs when k = n (all moves removed), which isn't the case in this example.

Consider revising the trace to show each removal explicitly with the resulting move sequence and final coordinate to improve clarity.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d14f1ba and 0f77f7f.

📒 Files selected for processing (20)
  • explanations/3643/en.md (1 hunks)
  • explanations/3644/en.md (1 hunks)
  • explanations/3645/en.md (1 hunks)
  • explanations/3648/en.md (1 hunks)
  • explanations/3649/en.md (1 hunks)
  • explanations/3653/en.md (1 hunks)
  • explanations/3675/en.md (1 hunks)
  • explanations/3690/en.md (1 hunks)
  • explanations/3694/en.md (1 hunks)
  • explanations/3698/en.md (1 hunks)
  • solutions/3643/01.py (1 hunks)
  • solutions/3644/01.py (1 hunks)
  • solutions/3645/01.py (1 hunks)
  • solutions/3648/01.py (1 hunks)
  • solutions/3649/01.py (1 hunks)
  • solutions/3653/01.py (1 hunks)
  • solutions/3675/01.py (1 hunks)
  • solutions/3690/01.py (1 hunks)
  • solutions/3694/01.py (1 hunks)
  • solutions/3698/01.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
solutions/3653/01.py (1)
visualizations/3623/01.jsx (1)
  • MOD (39-39)
🪛 LanguageTool
explanations/3648/en.md

[style] ~28-~28: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...needed horizontally: ceil(n / size). 3. Calculate sensors needed vertically: ceil(m / siz...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

explanations/3690/en.md

[style] ~9-~9: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...nput Size:** Array length is at most 6 (very small). - Time Complexity: O(6! * 6^2) in...

(EN_WEAK_ADJECTIVE)

🪛 Ruff (0.14.8)
solutions/3649/01.py

2-2: Undefined name List

(F821)

solutions/3643/01.py

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


3-3: Comment contains ambiguous × (MULTIPLICATION SIGN). Did you mean x (LATIN SMALL LETTER X)?

(RUF003)

solutions/3653/01.py

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


6-6: Ambiguous variable name: l

(E741)

solutions/3644/01.py

2-2: Undefined name List

(F821)

solutions/3645/01.py

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


8-8: Loop control variable i not used within loop body

Rename unused i to _i

(B007)


8-8: Ambiguous variable name: l

(E741)


8-8: zip() without an explicit strict= parameter

Add explicit value for parameter strict=

(B905)

solutions/3698/01.py

2-2: Undefined name List

(F821)


4-4: Ambiguous variable name: l

(E741)


12-12: Ambiguous variable name: l

(E741)

solutions/3690/01.py

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


18-18: Ambiguous variable name: l

(E741)

⏰ 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 (10)
solutions/3675/01.py (1)

1-8: LGTM!

The implementation correctly computes the circular distance from 'a' for each character and returns the maximum. The logic is clean and efficient.

solutions/3648/01.py (1)

1-6: LGTM!

The implementation correctly calculates the minimum number of sensors using ceiling division. The formula is efficient and mathematically sound.

explanations/3643/en.md (1)

1-56: LGTM! Clear and well-structured explanation.

The explanation provides a comprehensive walkthrough of the vertical submatrix flip strategy with appropriate complexity analysis, example trace, and final result verification.

explanations/3698/en.md (1)

1-64: LGTM! Well-documented two-pointer approach.

The explanation clearly outlines the strategy for finding the optimal split point in a mountain array with detailed trace walkthrough and complexity analysis.

explanations/3649/en.md (1)

1-52: LGTM! Clear two-pointer strategy for pair counting.

The explanation effectively describes the optimization from O(n²) brute force to O(n log n) with sorting and two pointers, including a detailed trace walkthrough.

explanations/3653/en.md (1)

1-64: LGTM! Straightforward simulation approach.

The explanation clearly documents the query processing strategy with appropriate complexity analysis and a complete example walkthrough.

explanations/3690/en.md (1)

1-64: LGTM! Comprehensive BFS strategy explanation.

The explanation clearly documents the state-space exploration approach with appropriate complexity analysis for the small input constraint. The example walkthrough effectively demonstrates the operation.

explanations/3648/en.md (1)

1-58: LGTM! Clear mathematical approach for sensor coverage.

The explanation effectively describes the optimal grid tiling strategy with straightforward arithmetic calculation, including appropriate complexity analysis and example verification.

explanations/3675/en.md (1)

1-57: LGTM!

The explanation clearly describes the circular alphabet distance strategy. The mathematical formulas and trace walkthrough are accurate, and the complexity analysis is appropriate for the problem.

solutions/3690/01.py (1)

16-32: Constraint assumption is incorrect.

The array length is at most 6, making the O(n⁴) approach entirely acceptable. With n ≤ 6, the algorithm generates at most 1,296 operations per BFS level, which poses no performance concern. The BFS solution is appropriate for this problem.

Likely an incorrect or invalid review comment.

Comment on lines +46 to +51
| Index | Value | Correct? | Mask Update | Mask Value |
|-------|-------|----------|-------------|------------|
| 0 | 0 | Yes (0==0) | Skip | (1<<30)-1 |
| 1 | 3 | No (3≠1) | mask &= 3 | 3 |
| 2 | 2 | No (2≠2) | mask &= 2 | 3 & 2 = 2 |
| 3 | 1 | No (1≠3) | mask &= 1 | 2 & 1 = 0 |
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

Correctness error in trace table (line 50).

The table incorrectly marks index 2 as misplaced:

Index Value Correct? Mask Update Mask Value
2 2 No (2≠2) mask &= 2 3 & 2 = 2

Since 2 == 2, the element at index 2 is correctly placed. The row should indicate "Yes (2==2)" and "Skip" for the mask update.

Corrected trace:

For nums = [0,3,2,1]:

  • Index 0: value 0, correct (0==0) → Skip
  • Index 1: value 3, incorrect (3≠1) → mask &= 3 → mask = 3
  • Index 2: value 2, correct (2==2) → Skip
  • Index 3: value 1, incorrect (1≠3) → mask &= 1 → mask = 3 & 1 = 1

The final mask should be 1, not 0.

🤖 Prompt for AI Agents
In explanations/3644/en.md around lines 46 to 51, the trace table incorrectly
marks index 2 as misplaced; change the row for index 2 to show "Yes (2==2)" and
"Skip" for the mask update, and update subsequent mask calculations accordingly
so the final mask becomes 1 instead of 0 (adjust the narrative and the mask
value cells for index 3 to reflect mask = 3 & 1 = 1).

Comment on lines 1 to 2
class Solution:
def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
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

Add missing import for type hints.

The List type hint is used but not imported, causing a NameError at runtime when type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
📝 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
class Solution:
def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
from typing import List
class Solution:
def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3643/01.py around lines 1 to 2, the function signature uses the
List type hint but List is not imported, causing a NameError when evaluating
annotations; add the missing import (e.g., from typing import List) at the top
of the file so that List is defined for type hints.

Comment on lines +1 to +2
class Solution:
def sortPermutation(self, nums: List[int]) -> int:
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

Add missing import for type hints.

The List type hint is used but not imported, which will cause a NameError at runtime when type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def sortPermutation(self, nums: List[int]) -> int:
📝 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
class Solution:
def sortPermutation(self, nums: List[int]) -> int:
from typing import List
class Solution:
def sortPermutation(self, nums: List[int]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3644/01.py around lines 1 to 2, the function uses the type hint
List but the List symbol is not imported; add the missing import by importing
List (e.g., from typing import List) at the top of the file so the type hint
resolves correctly and avoids a NameError.

Comment on lines +1 to +2
class Solution:
def maxTotal(self, value: List[int], limit: List[int]) -> int:
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

Add missing import for type hints.

The List type hint is used but not imported, causing a NameError at runtime when type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def maxTotal(self, value: List[int], limit: List[int]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3645/01.py around lines 1 to 2, the type hint List is referenced
but not imported, causing a NameError; fix by adding the missing import
statement (e.g., add "from typing import List") at the top of the file before
the Solution class so the type hint resolves correctly.

Comment on lines +1 to +2
class Solution:
def perfectPairs(self, nums: List[int]) -> int:
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

Add missing import for type hints.

The List type hint is used but not imported, causing a NameError at runtime when type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def perfectPairs(self, nums: List[int]) -> int:
📝 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
class Solution:
def perfectPairs(self, nums: List[int]) -> int:
from typing import List
class Solution:
def perfectPairs(self, nums: List[int]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3649/01.py around lines 1 to 2, the function signature uses the
type hint List but List is not imported; add the missing import by adding "from
typing import List" (or using built-in list annotation if targeting Python 3.9+)
at the top of the file so the type hint resolves and avoids NameError.

Comment on lines +1 to +2
class Solution:
def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
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

Add missing import for type hints.

The List type hint is used but not imported, which will cause a NameError at runtime when the type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
📝 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
class Solution:
def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
from typing import List
class Solution:
def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3653/01.py around lines 1 to 2, the function signature uses the
List type hint but List is not imported; add the missing import by adding "from
typing import List" at the top of the file (before the class) so the type hint
resolves correctly.

Comment on lines +1 to +2
class Solution:
def minSplitMerge(self, nums1: List[int], nums2: List[int]) -> int:
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

Missing import for List type hint.

The List type from the typing module is used in the method signature but never imported, which will cause a NameError at runtime.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def minSplitMerge(self, nums1: List[int], nums2: List[int]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)


2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3690/01.py around lines 1 to 2, the function signature uses the
List type hint but the List symbol is not imported; add the missing import by
importing List from the typing module at the top of the file (e.g., add "from
typing import List") so the type annotation resolves and avoids a NameError.

Comment on lines +18 to +32
for l in range(n):
for r in range(l, n):
# Remove subarray [l..r]
removed = state[l:r+1]
prefix = state[:l]
suffix = state[r+1:]

# Try inserting at all possible positions
for pos in range(len(prefix) + len(suffix) + 1):
new_state = prefix[:pos] + removed + prefix[pos:] + suffix
new_state_tuple = tuple(new_state)

if new_state_tuple not in visited:
visited.add(new_state_tuple)
queue.append((new_state_tuple, ops + 1))
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

Critical logic error in state generation (line 27).

After removing state[l:r+1], the remaining elements are prefix + suffix. When inserting removed at position pos, the insertion should happen within the concatenated remaining array. However, line 27 incorrectly inserts into prefix only:

new_state = prefix[:pos] + removed + prefix[pos:] + suffix

When pos > len(prefix), this produces prefix + removed + suffix, which only inserts after the prefix, not at the intended position within the remaining array.

Example:

  • state = (1, 2, 3, 4, 5), remove indices [1:2] → removed = (2, 3), prefix = (1,), suffix = (4, 5)
  • Remaining array: (1, 4, 5)
  • To insert at pos=2 in remaining: should get (1, 4, 2, 3, 5)
  • Current code with pos=2: prefix[:2] + removed + prefix[2:] + suffix = (1,) + (2, 3) + () + (4, 5) = (1, 2, 3, 4, 5)
🔎 Proposed fix
                     # Try inserting at all possible positions
+                    remaining = prefix + suffix
                     for pos in range(len(prefix) + len(suffix) + 1):
-                        new_state = prefix[:pos] + removed + prefix[pos:] + suffix
+                        new_state = remaining[:pos] + removed + remaining[pos:]
                         new_state_tuple = tuple(new_state)
🧰 Tools
🪛 Ruff (0.14.8)

18-18: Ambiguous variable name: l

(E741)

🤖 Prompt for AI Agents
In solutions/3690/01.py around lines 18 to 32, the code inserts the removed
slice into only the prefix which breaks insertion positions beyond the prefix;
compute the remaining sequence as remaining = prefix + suffix and then build the
new state by inserting removed into remaining at pos: new_state =
remaining[:pos] + removed + remaining[pos:], and iterate pos from 0 to
len(remaining) inclusive so all insertion positions in the concatenated
remaining array are considered.

Comment on lines +6 to +29
# Sliding window: simulate removing each substring of length k
# Start by processing characters from k onwards
for i in range(k, len(s)):
# Add effect of new character at position i
if s[i] == 'U':
y += 1
elif s[i] == 'D':
y -= 1
elif s[i] == 'L':
x -= 1
elif s[i] == 'R':
x += 1

# Remove effect of character at position i - k (leaving the window)
if s[i - k] == 'U':
y -= 1
elif s[i - k] == 'D':
y += 1
elif s[i - k] == 'L':
x += 1
elif s[i - k] == 'R':
x -= 1

seen.add((x, y))
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

🧩 Analysis chain

🏁 Script executed:

python3 << 'EOF'
def distinctPoints_current(s: str, k: int) -> int:
    """Current implementation from the PR"""
    seen = {(0, 0)}
    x = y = 0
    
    for i in range(k, len(s)):
        if s[i] == 'U':
            y += 1
        elif s[i] == 'D':
            y -= 1
        elif s[i] == 'L':
            x -= 1
        elif s[i] == 'R':
            x += 1
        
        if s[i - k] == 'U':
            y -= 1
        elif s[i - k] == 'D':
            y += 1
        elif s[i - k] == 'L':
            x += 1
        elif s[i - k] == 'R':
            x -= 1
        
        seen.add((x, y))
    
    return len(seen)

def distinctPoints_bruteforce(s: str, k: int) -> int:
    """Brute force: try removing each k-length substring"""
    seen = {(0, 0)}
    
    for start in range(len(s) - k + 1):
        # Remove substring s[start:start+k]
        remaining = s[:start] + s[start+k:]
        x = y = 0
        for ch in remaining:
            if ch == 'U':
                y += 1
            elif ch == 'D':
                y -= 1
            elif ch == 'L':
                x -= 1
            elif ch == 'R':
                x += 1
        seen.add((x, y))
    
    return len(seen)

# Test cases
test_cases = [
    ("UDLR", 2),
    ("UURR", 2),
    ("UDLR", 1),
    ("UUDD", 2),
]

for s, k in test_cases:
    current = distinctPoints_current(s, k)
    brute = distinctPoints_bruteforce(s, k)
    match = "✓" if current == brute else "✗"
    print(f"{match} s='{s}', k={k}: current={current}, brute={brute}")
EOF

Repository: romankurnovskii/leetcode-apps

Length of output: 216


The sliding window implementation fails to correctly track all k-length substring removals.

Test verification reveals the algorithm produces incorrect results for multiple cases: s='UURR' with k=2 returns 3 distinct points instead of 4, and s='UDLR' with k=1 returns 4 instead of 5. The sliding window approach only tracks cumulative position changes at specific iterations rather than computing the final position after each independent k-length substring removal.

To fix, either explicitly remove each substring and compute final positions, or precompute prefix/suffix sums to calculate O(1) effects for each of the (len(s) - k + 1) possible removals.

🤖 Prompt for AI Agents
In solutions/3694/01.py around lines 6 to 29, the sliding-window mutating of x,y
is incorrect because it tracks incremental changes rather than computing the
final position after independently removing each k-length substring; fix by
computing prefix displacements and using them to get each removal's final
position in O(1): build pos array where pos[i] is (x,y) after the first i
characters, let total = pos[n], then for each removal start i in [0..n-k]
compute final = pos[i] + (total - pos[i+k]) and add final to seen;
alternatively, if you prefer simplicity, explicitly simulate removing each
substring by concatenating s[:i] + s[i+k:] and computing its final displacement,
but the prefix approach is preferred for O(n).

Comment on lines +1 to +2
class Solution:
def splitArray(self, nums: List[int]) -> int:
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

Add missing import for type hints.

The List type hint is used but not imported, causing a NameError at runtime when type hints are evaluated.

🔎 Proposed fix
+from typing import List
+
 class Solution:
     def splitArray(self, nums: List[int]) -> int:
📝 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
class Solution:
def splitArray(self, nums: List[int]) -> int:
from typing import List
class Solution:
def splitArray(self, nums: List[int]) -> int:
🧰 Tools
🪛 Ruff (0.14.8)

2-2: Undefined name List

(F821)

🤖 Prompt for AI Agents
In solutions/3698/01.py around lines 1 to 2, the type hint List is referenced
but not imported, causing a NameError; fix by adding the missing import
statement from the typing module (from typing import List) at the top of the
file so the List type hint is defined, or alternatively change the annotation to
use built-in list if targeting Python 3.9+.

@romankurnovskii romankurnovskii merged commit 78d7da6 into main Dec 19, 2025
3 checks passed
@romankurnovskii romankurnovskii deleted the problems-3705-3698-3694-3690-3675-3653-3649-3648-3645-3644-3643 branch December 19, 2025 06:24
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