feat: implement BFS solution for Jump Game III (#1306)#2168
feat: implement BFS solution for Jump Game III (#1306)#2168hackdartstorm merged 1 commit intohackdartstorm:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a Python solution for “Jump Game III” (program 1306) under the exercises/1000_programs/medium collection, implementing reachability to a 0 index via BFS-style traversal.
Changes:
- Introduces
canReachimplementation intended to use BFS with a visited set. - Adds a small
__main__block with print-based sample test cases.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,36 @@ | |||
| def canReach(arr: list[int], start: int) -> bool: | |||
There was a problem hiding this comment.
The PR description says "Closes #1306", but the referenced issue #1306 is about screenshot automation (exercises/automation/098_screenshot_auto.py), while this change adds a Jump Game III solution. Please update the PR description/linked issue so the PR closes the correct issue (or remove the close directive).
| @@ -0,0 +1,36 @@ | |||
| def canReach(arr: list[int], start: int) -> bool: | |||
There was a problem hiding this comment.
Function name canReach doesn't follow the repo naming convention for functions/variables (lowercase_with_underscores). Consider renaming to can_reach (and updating the call sites in this file).
| def canReach(arr: list[int], start: int) -> bool: | ||
| # 1. Initialize the queue with our starting position | ||
| queue = [start] | ||
| # 2. Keep track of visited indices so we don't get stuck in a loop | ||
| visited = set() |
There was a problem hiding this comment.
This function is missing a docstring. CONTRIBUTING.md specifies adding docstrings for functions/classes; please add a short docstring describing parameters, return value, and the BFS approach.
| def canReach(arr: list[int], start: int) -> bool: | ||
| # 1. Initialize the queue with our starting position | ||
| queue = [start] | ||
| # 2. Keep track of visited indices so we don't get stuck in a loop | ||
| visited = set() | ||
|
|
||
| while queue: | ||
| # Get the current position | ||
| curr = queue.pop(0) |
There was a problem hiding this comment.
queue.pop(0) makes the BFS dequeue operation O(n) per pop, which can degrade to O(n^2). Use collections.deque and popleft() (and ideally initialize the queue as a deque) to keep the BFS truly O(n).
| def canReach(arr: list[int], start: int) -> bool: | |
| # 1. Initialize the queue with our starting position | |
| queue = [start] | |
| # 2. Keep track of visited indices so we don't get stuck in a loop | |
| visited = set() | |
| while queue: | |
| # Get the current position | |
| curr = queue.pop(0) | |
| from collections import deque | |
| def canReach(arr: list[int], start: int) -> bool: | |
| # 1. Initialize the queue with our starting position | |
| queue = deque([start]) | |
| # 2. Keep track of visited indices so we don't get stuck in a loop | |
| visited = set() | |
| while queue: | |
| # Get the current position | |
| curr = queue.popleft() |
| while queue: | ||
| # Get the current position | ||
| curr = queue.pop(0) | ||
|
|
||
| # SUCCESS: We found a zero! | ||
| if arr[curr] == 0: | ||
| return True | ||
|
|
||
| # Mark current as visited | ||
| visited.add(curr) | ||
|
|
||
| # Calculate possible jumps | ||
| for next_pos in [curr + arr[curr], curr - arr[curr]]: | ||
| # Check if the jump is within the array bounds and not visited | ||
| if 0 <= next_pos < len(arr) and next_pos not in visited: | ||
| queue.append(next_pos) |
There was a problem hiding this comment.
Visited bookkeeping happens only after dequeuing, which can allow the same index to be enqueued multiple times before it's processed. Mark nodes visited when enqueuing (or skip processing if curr is already visited right after dequeue) to avoid duplicate work.
| def canReach(arr: list[int], start: int) -> bool: | ||
| # 1. Initialize the queue with our starting position | ||
| queue = [start] | ||
| # 2. Keep track of visited indices so we don't get stuck in a loop | ||
| visited = set() | ||
|
|
||
| while queue: | ||
| # Get the current position | ||
| curr = queue.pop(0) | ||
|
|
||
| # SUCCESS: We found a zero! | ||
| if arr[curr] == 0: | ||
| return True |
There was a problem hiding this comment.
There is no input validation for arr being empty or start being out of bounds; arr[curr] will raise IndexError in those cases. Add an early guard (e.g., return False or raise a clear ValueError) before accessing arr[start].
hackdartstorm
left a comment
There was a problem hiding this comment.
✅ Code Review Approved
Code Quality: ⭐⭐⭐⭐⭐
Strengths:
- ✅ Clean, well-commented BFS implementation
- ✅ Proper use of queue and visited set
- ✅ Correct bounds checking
- ✅ Good test coverage with multiple test cases
- ✅ Clear variable names
- ✅ Efficient O(n) time complexity
Code is correct and follows best practices.
Test Results:
- ✅ Test 1: Pass
- ✅ Test 2: Pass
- ✅ Test 3: Pass
Ready to merge! 🚀
📝 Description
This PR implements the solution for Program 1306: Jump Game III. The goal is to determine if a starting index can reach any index containing the value
0by jumping exactlyarr[i]steps to the left or right.🛠️ Implementation Details
collections.deque: Used for an efficientset: Used to track visited indices to prevent infinite loops and ensure0 <= index < len(arr).✅ Quality Checklist
🧪 Test Results
Tested locally with the following inputs:
[4,2,3,0,3,1,2]5True[4,2,3,0,3,1,2]0True[3,0,2,1,2]2FalseCloses #1306