Frog Jump
Master this topic with zero to advance depth.
Frog Jump
A frog is crossing a river. The river is divided into units and at each unit there may or may not be a stone. The frog can jump on a stone, but it must not jump into the water.
Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.
If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.
Visual Representation
Stones: [0, 1, 3, 5, 6, 8, 12, 17]
Jump 1: 0 -> 1 (Size 1)
Jump 2: 1 -> 3 (Size 2, allowed: 1-1, 1, 1+1)
Jump 3: 3 -> 5 (Size 2, allowed: 1, 2, 3)
...Examples
0->1(1)->3(2)->5(2)->8(3)->12(4)->17(5)
Level I: Brute Force (Recursion)
Intuition
Try every valid jump from the current stone. For a stone at index i reached with a jump of k, the next jump can be k-1, k, or k+1.
Thought Process
- Start at the first stone.
- From stone at position
pos, if we reached it with jumpk, try positionspos + k - 1,pos + k, andpos + k + 1. - Base case: If we reach the last stone, return
true. - If the target position has a stone, recurse.
Detailed Dry Run
stones = [0, 1, 3]
- Start at 0. Only way to start is jump 1 to stone 1.
- At 1, last jump was 1. Next jumps: 0 (skip), 1, 2.
- Try k=2: 1 + 2 = 3. Stone 3 exists! Reached target.
Level II: Memoization (Top-Down)
Intuition
Cache (position, lastJump) states to avoid recomputing the same frog position visited with the same jump size.
Visual
stones=[0,1,3,5,6], target=6
solve(1, 1): -> solve(3, 2) or solve(3, 1)
solve(3,2): cached after first call!Detailed Dry Run
Cache key=(pos, k). solve(1,1) -> solve(3,2). solve(3,2) -> solve(5,2) or solve(5,3). Cached when revisited.
Level III: Dynamic Programming (Map of Sets)
Intuition
We maintain a map where the key is the stone's position and the value is a set of all possible jump sizes that could have landed the frog on that stone.
Thought Process
- Initialize
Map<Integer, Set<Integer>>. For each stone, create an empty set. - Add jump size
0to the first stone (base case). - For each stone
s:- For each jump size
kinmap.get(s):- For each next jump
stepin{k-1, k, k+1}:- If
step > 0andmap.containsKey(s + step):- Add
stepto the set for stones + step.
- Add
- If
- For each next jump
- For each jump size
- If the set for the last stone is not empty, return
true.
Detailed Dry Run
stones = [0, 1, 3]
| Stone | Jump Sizes |
|---|---|
| 0 | {1} (Initial jump is 1) |
| 1 | {1} (from 0+1) |
| 3 | {2} (from 1+2, k=1 -> k+1=2) |
| Result: True (Set for 3 is not empty) |
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.