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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
* Greedy
* Gas Stations
* [Test Gas Stations](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/gas_stations/test_gas_stations.py)
* Jump Game
* [Test Jump Game](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/jump_game/test_jump_game.py)
Comment on lines +88 to +89
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix markdown list indentation for consistency.

The indentation for the Jump Game entry is inconsistent with other entries in the file. Static analysis detected this as a formatting issue.

Apply this diff to fix the indentation:

   * Greedy
     * Gas Stations
       * [Test Gas Stations](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/gas_stations/test_gas_stations.py)
-    * Jump Game
-      * [Test Jump Game](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/jump_game/test_jump_game.py)
+    * Jump Game
+      * [Test Jump Game](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/jump_game/test_jump_game.py)
     * Majority Element
       * [Test Majority Element](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/majority_element/test_majority_element.py)

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

88-88: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


89-89: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)

🤖 Prompt for AI Agents
In DIRECTORY.md around lines 88 to 89, the "Test Jump Game" list item is
misindented relative to its parent "Jump Game" bullet; fix the markdown list
indentation so the test entry is a proper sub-item (align with other entries by
adding the same amount of leading spaces used for nested list items in this
file, e.g., two spaces) so both lines use consistent indentation.

* Majority Element
* [Test Majority Element](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/majority_element/test_majority_element.py)
* Min Arrows
Expand Down Expand Up @@ -497,8 +499,6 @@
* [Test H Index](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/h_index/test_h_index.py)
* Increasing Triplet Subsequence
* [Test Increasing Triplet](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/increasing_triplet_subsequence/test_increasing_triplet.py)
* Jump Game
* [Test Jump Game](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/jump_game/test_jump_game.py)
* Kid With Greatest No Of Candies
* [Test Kids With Greatest Candies](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/kid_with_greatest_no_of_candies/test_kids_with_greatest_candies.py)
* Longest Increasing Subsequence
Expand Down
205 changes: 205 additions & 0 deletions algorithms/greedy/jump_game/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Jump Game

You are given an integer array nums. You are initially positioned at the array's first index, and each element in the
array represents your maximum jump length at that position.

Return true if you can reach the last index, or false otherwise.

```text
Example 1:

Input: nums = [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
```

```text
Example 2:

Input: nums = [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible
to reach the last index.
```

## Solutions

1. [Naive Approach](#naive-approach)
1. [Optimized Approach using Greedy Pattern](#optimized-approach-using-greedy-pattern)

### Naive Approach

The naive approach explores all possible jump sequences from the starting position to the end of the array. It begins
at the first index and attempts to jump to every reachable position from the current index, recursively repeating this
process for each new position. If a path successfully reaches the last index, the algorithm returns success. If it
reaches a position without further moves, it backtracks to try a different path.

While this method guarantees that all possible paths are considered, it is highly inefficient, as it explores many
redundant or dead-end routes. The time complexity of this backtracking approach is exponential, making it impractical
for large inputs.

### Optimized Approach using Greedy Pattern

An optimized way to solve this problem is using a greedy approach that works in reverse. Instead of trying every
possible forward jump, we flip the logic: start from the end and ask, “Can we reach this position from any earlier index?”

We begin with the last index as our initial target—the position we want to reach. Then, we move backward through the
array, checking whether the current index has a jump value large enough to reach or go beyond the current target. If it
can, we update the target to that index. This means that reaching this earlier position would eventually allow us to
reach the end. By continuously updating the target, we’re effectively identifying the leftmost position from which the
end is reachable.

This process continues until we reach the first index or determine that no earlier index can reach the current target.
If we finish with the target at index 0, it means the start of the array can lead to the end, so we return TRUE. If the
target remains beyond index 0, then no path exists from the start to the end, and we return FALSE.

![Solution 1](./images/solutions/jump_game_1_solution_1.png)
![Solution 2](./images/solutions/jump_game_1_solution_2.png)
![Solution 3](./images/solutions/jump_game_1_solution_3.png)
![Solution 4](./images/solutions/jump_game_1_solution_4.png)
![Solution 5](./images/solutions/jump_game_1_solution_5.png)
![Solution 6](./images/solutions/jump_game_1_solution_6.png)
![Solution 7](./images/solutions/jump_game_1_solution_7.png)
![Solution 8](./images/solutions/jump_game_1_solution_8.png)
![Solution 9](./images/solutions/jump_game_1_solution_9.png)
![Solution 10](./images/solutions/jump_game_1_solution_10.png)
![Solution 11](./images/solutions/jump_game_1_solution_11.png)

#### Algorithm

1. We begin by setting the last index of the array as our initial target using the variable target = len(nums) - 1. This
target represents the position we are trying to reach, starting from the end and working backward. By initializing the
target this way, we define our goal: to find out if there is any index i from which the target is reachable based on the
value at that position, nums[i]. This also sets the stage for updating the target if such an index is found.

2. Next, we loop backward through the array using for i in range(len(nums) - 2, -1, -1). Here, i represents the current
index we are analyzing. At each index i, the value nums[i] tells us how far we can jump forward from that position.
By checking whether i + nums[i] >= target, we determine whether it can reach the current target from index i. This
step allows us to use the jump range at each position to decide if it can potentially lead us to the end.

3. If the condition i + nums[i] >= target is TRUE, the current index i can jump far enough to reach the current target.
In that case, we update target = i, effectively saying, “Now we just need to reach index i instead.” If the condition
fails, we move back in the array one step further and try again with the previous index.
We repeat this process until we either:
- Successfully moving the target back to index 0 means the start of the array can reach the end. In this case, we
return TRUE.
- Or reach the start without ever being able to update the target to 0, which means there is no valid path. In this
case, we return FALSE.

#### Solution Summary

1. Set the last index of the array as the target index.
2. Traverse the array backward and verify if we can reach the target index from any of the previous indexes.
- If we can reach it, we update the target index with the index that allows us to jump to the target index.
- We repeat this process until we’ve traversed the entire array.
3. Return TRUE if, through this process, we can reach the first index of the array. Otherwise, return FALSE.

#### Time Complexity

The time complexity of the above solution is O(n), since we traverse the array only once, where n is the number of
elements in the array.

#### Space Complexity

The space complexity of the above solution is O(1), because we do not use any extra space.


---

# Jump Game II

You are given a 0-indexed array of integers nums of length n. You are initially positioned at nums[0].

Each element nums[i] represents the maximum length of a forward jump from index i. In other words, if you are at
nums[i], you can jump to any nums[i + j] where:

0 <= j <= nums[i] and
i + j < n
Return the minimum number of jumps to reach nums[n - 1]. The test cases are generated such that you can reach
nums[n - 1].

```text
Example 1:

Input: nums = [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to
the last index.
```

```text
Example 2:

Input: nums = [2,3,0,1,4]
Output: 2
```

![Example 1](./images/examples/jump_game_2_example_1.png)
![Example 2](./images/examples/jump_game_2_example_2.png)
![Example 3](./images/examples/jump_game_2_example_3.png)
![Example 4](./images/examples/jump_game_2_example_4.png)
![Example 5](./images/examples/jump_game_2_example_5.png)
![Example 6](./images/examples/jump_game_2_example_6.png)

## Solution

We’ll solve this problem using a greedy approach. At each step, we choose the jump that allows us to reach the farthest
point. The objective is to minimize the number of jumps required to reach the end of the array. This strategy is
considered greedy because it selects the best possible move at each step without considering the impact on future jumps.
By always jumping as far as possible, we cover more distance and use fewer jumps to reach the end.

To find the minimum number of jumps needed to reach the end of the array, keep track of how far you can go with the
current number of jumps. As you progress through the array, update this maximum reach based on your current position.
When you reach the limit of your current jump range, increase your jump count and adjust the range to the farthest
position you can reach with the next jump. Continue this process until you reach or exceed the end of the array.

The steps of the algorithm are given below:

1. Initialize three variables, all set to 0.
- `jumps`: This variable tracks the minimum number of jumps required to reach the end of the array and will be
returned as the final output.
- `current_jump_boundary`: This represents the maximum index we can reach with the current number of jumps. It acts
as the boundary of how far we can go before making another jump.
- `farthest_jump_index`: This tracks the farthest index we can reach from the current position by considering all
possible jumps within the current jump’s range.

2. Iterate through the nums array and perform the following steps:
- Update `farthest_jump_index`: For each index i, calculate i + nums[i], which represents the farthest index we can
reach from i. Update farthest_jump_index to be the maximum of its current value and i + nums[i].
- Check if a new jump is needed: If i equals current_jump_boundary, it means we’ve reached the limit of the current
jump. Increment jumps by 1, and update current_jump_boundary to farthest_jump_index to set up for the next jump.

3. After iterating through the array, jumps will contain the minimum number of jumps needed to reach the end. Return
this value as the output.

Let’s look at the following illustration to get a better understanding of the solution:

![Solution 1](./images/solutions/jump_game_2_solution_1.png)
![Solution 2](./images/solutions/jump_game_2_solution_2.png)
![Solution 3](./images/solutions/jump_game_2_solution_3.png)
![Solution 4](./images/solutions/jump_game_2_solution_4.png)
![Solution 5](./images/solutions/jump_game_2_solution_5.png)
![Solution 6](./images/solutions/jump_game_2_solution_6.png)
![Solution 7](./images/solutions/jump_game_2_solution_7.png)
![Solution 8](./images/solutions/jump_game_2_solution_8.png)
![Solution 9](./images/solutions/jump_game_2_solution_9.png)
![Solution 10](./images/solutions/jump_game_2_solution_10.png)
![Solution 11](./images/solutions/jump_game_2_solution_11.png)
![Solution 12](./images/solutions/jump_game_2_solution_12.png)
![Solution 13](./images/solutions/jump_game_2_solution_13.png)

### Time Complexity

The time complexity of the above solution is O(n), where n is the length of nums because we are iterating the array once.

### Space Complexity

The space complexity of the above solution is O(1), because we are not using any extra space.

---

# Topics

- Array
- Dynamic Programming
- Greedy
127 changes: 127 additions & 0 deletions algorithms/greedy/jump_game/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from typing import List


def can_jump(nums: List[int]) -> bool:
"""
This function checks if it is possible to reach the last index of the array from the first index.
Args:
nums(list): list of integers
Returns:
bool: True if can jump to the last index, False otherwise
"""

current_position = nums[0]

for idx in range(1, len(nums)):
if current_position == 0:
return False

current_position -= 1

current_position = max(current_position, nums[idx])

return True
Comment on lines +4 to +23
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add input validation for empty arrays.

The function will raise an IndexError when accessing nums[0] if the input array is empty. While the test data doesn't include empty arrays, adding a guard check would make the function more robust.

Consider adding validation at the beginning:

 def can_jump(nums: List[int]) -> bool:
     """
     This function checks if it is possible to reach the last index of the array from the first index.
     Args:
         nums(list): list of integers
     Returns:
         bool: True if can jump to the last index, False otherwise
     """
+    if not nums:
+        return True  # or raise ValueError("Input array cannot be empty")
 
     current_position = nums[0]
🤖 Prompt for AI Agents
In algorithms/greedy/jump_game/__init__.py around lines 4 to 23, the function
reads nums[0] without checking for an empty list which raises IndexError; add an
input validation guard at the top (e.g., if not nums: return False or decide
appropriate behavior) before accessing nums[0], and keep the rest of the
algorithm unchanged so empty inputs are handled safely.



def can_jump_2(nums: List[int]) -> bool:
"""
This function checks if it is possible to reach the last index of the array from the first index.
This variation starts checking from the last element in the input list and tracking back to check if it is possible
to reach the end.
Args:
nums(list): list of integers
Returns:
bool: True if can jump to the last index, False otherwise
"""
target_num_index = len(nums) - 1

for idx in range(len(nums) - 2, -1, -1):
if target_num_index <= idx + nums[idx]:
target_num_index = idx

if target_num_index == 0:
return True
return False
Comment on lines +26 to +46
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add input validation and simplify return statement.

  1. The function doesn't handle empty arrays. If nums = [], target_num_index becomes -1, and the function returns False, which may not be the intended behavior.

  2. The return statement can be simplified to a single line.

Apply this diff to address both issues:

 def can_jump_2(nums: List[int]) -> bool:
     """
     This function checks if it is possible to reach the last index of the array from the first index.
 
     This variation starts checking from the last element in the input list and tracking back to check if it is possible
     to reach the end.
 
     Args:
         nums(list): list of integers
     Returns:
         bool: True if can jump to the last index, False otherwise
     """
+    if not nums:
+        return True  # or raise ValueError("Input array cannot be empty")
+
     target_num_index = len(nums) - 1
 
     for idx in range(len(nums) - 2, -1, -1):
         if target_num_index <= idx + nums[idx]:
             target_num_index = idx
 
-    if target_num_index == 0:
-        return True
-    return False
+    return target_num_index == 0
📝 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
def can_jump_2(nums: List[int]) -> bool:
"""
This function checks if it is possible to reach the last index of the array from the first index.
This variation starts checking from the last element in the input list and tracking back to check if it is possible
to reach the end.
Args:
nums(list): list of integers
Returns:
bool: True if can jump to the last index, False otherwise
"""
target_num_index = len(nums) - 1
for idx in range(len(nums) - 2, -1, -1):
if target_num_index <= idx + nums[idx]:
target_num_index = idx
if target_num_index == 0:
return True
return False
def can_jump_2(nums: List[int]) -> bool:
"""
This function checks if it is possible to reach the last index of the array from the first index.
This variation starts checking from the last element in the input list and tracking back to check if it is possible
to reach the end.
Args:
nums(list): list of integers
Returns:
bool: True if can jump to the last index, False otherwise
"""
if not nums:
return True # or raise ValueError("Input array cannot be empty")
target_num_index = len(nums) - 1
for idx in range(len(nums) - 2, -1, -1):
if target_num_index <= idx + nums[idx]:
target_num_index = idx
return target_num_index == 0
🤖 Prompt for AI Agents
In algorithms/greedy/jump_game/__init__.py around lines 26 to 46, add input
validation to handle an empty list by returning False early (e.g., if not nums:
return False), then simplify the final return to a single-line boolean
expression (return target_num_index == 0); keep the existing backward scan logic
unchanged.



def jump(nums: List[int]) -> int:
"""
This function returns the minimum number of jumps needed to reach the last index of the array from the first index.
Args:
nums(list): list of integers
Returns:
int: minimum number of jumps needed to reach the last index
"""
size = len(nums)
# if start index == destination index == 0
if size == 1:
return 0

# destination is last index
destination = size - 1

# record of current coverage, record of last jump index
current_coverage, last_jump_index = 0, 0

# min number of jumps
min_jumps = 0

# Greedy strategy: extend coverage as long as possible with lazy jump
for idx in range(size):
# extend coverage as far as possible
current_coverage = max(current_coverage, idx + nums[idx])

# forced to jump (by lazy jump) to extend coverage
if idx == last_jump_index:
# update last jump index
last_jump_index = current_coverage

# update counter of jump by +1
min_jumps += 1

# check if destination has been reached
if current_coverage >= destination:
return min_jumps

return min_jumps


def jump_2(nums: List[int]) -> int:
"""
This function returns the minimum number of jumps needed to reach the last index of the array from the first index.
Args:
nums(list): list of integers
Returns:
int: minimum number of jumps needed to reach the last index
"""
# Store the length of the input array
size = len(nums)

# if start index == destination index == 0
if size == 1:
return 0

# Initialize the variables to track the number of jumps,
# the current jump's limit, and the farthest reachable index
min_jumps = 0
current_jump_boundary = 0
furthest_jump_index = 0

# Iterate through the array, stopping before the last element
for idx in range(size - 1):
# Update the farthest_jump_index to be the maximum of its current value
# and the index we can reach from the current position
furthest_jump_index = max(furthest_jump_index, idx + nums[idx])

# If we have reached the limit of the current jump
if idx == current_jump_boundary:
# update counter of jump by +1
min_jumps += 1

# Update the current_jump_boundary to the farthest we can reach
current_jump_boundary = furthest_jump_index

# Return the total number of jumps needed to reach the end of the array
return min_jumps
Comment on lines +91 to +127
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add validation for empty arrays.

Similar to the jump function, this implementation doesn't handle empty arrays. Add the same validation to prevent potential IndexError.

Apply this diff:

 def jump_2(nums: List[int]) -> int:
     """
     This function returns the minimum number of jumps needed to reach the last index of the array from the first index.
     Args:
         nums(list): list of integers
     Returns:
         int: minimum number of jumps needed to reach the last index
     """
     # Store the length of the input array
     size = len(nums)
 
     # if start index == destination index == 0
     if size == 1:
         return 0
+    if size == 0:
+        return 0  # or raise ValueError("Input array cannot be empty")
 
     # Initialize the variables to track the number of jumps,
     # the current jump's limit, and the farthest reachable index
     min_jumps = 0
🤖 Prompt for AI Agents
In algorithms/greedy/jump_game/__init__.py around lines 91 to 127, the jump_2
function lacks validation for an empty input list which can cause an IndexError;
add the same guard used in jump: check for an empty list (e.g., if not nums or
size == 0) immediately after computing size and return 0 (or the same expected
behavior as jump) before proceeding with the rest of the logic so no indexing
occurs on an empty array.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading