Red-Green-Code

Deliberate practice techniques for software developers

  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter

LeetCode 55: Jump Game

By Duncan Smith Jan 31 0

A robot walking on a number line

Let’s solve LeetCode problem 55 (Jump Game) using dynamic programming. Next week, we’ll consider a sneaky aspect of this problem.

The problem:

You are playing a game on a number line where the aim is to reach position n-1 starting from position 0. As input, you get an array nums of size n containing non-negative integers. From position i, you can move forward any distance between 0 and nums[i] (inclusive). Can you reach the last position to win the game?

Subproblems

To solve a dynamic programming problem, we need to break it down into subproblems and use the subproblems to solve the original problem.

The original problem asks if we can get to position n-1 from position 0. We could answer this by calculating the largest position we can reach from position 0, and checking if it’s at least n-1. Consider a function $f(x)$ that gives us the largest position we can reach from position $x$. Then, if $f(0) \geq n-1$, we win.

If nums[0] is 0, then it’s impossible to win the game. We can’t leave the starting position. But if nums[0] is anything else, we can get from position 0 to positions 1, 2, 3, up to position nums[0]. Using our function $f$, let $a_x =$ nums[x]. Then, if $a_x = 0$, $f(x) = x$. Otherwise, $f(x) = \max(f(x+1), f(x+2), …, f(x+a_x))$.

This definition of $f$ shows us the subproblems: $f(x+1), f(x+2)$, and so on. The subproblems are overlapping because we will need some of the same $f(x)$ values more than once. For example, if we can get from position 0 to positions 1 and 2, then we’ll need the solutions to $f(1)$ and $f(2)$. And if we can get from position 1 to position 2, then we’ll need the solution to $f(2)$ again.

Jump Game has optimal substructure because we can use optimal solutions to the subproblems to find an optimal solution to the original problem. Specifically, we need the largest member of a set of optimal subproblem solutions. Together, overlapping subproblems and optimal substructure are the characteristics of a dynamic programming problem.

Design

As usual, a top-down DP implementation comes naturally from the subproblem analysis. Let’s take the top-down approach.

Let farthest(pos, nums) be a recursive function that returns the farthest point reachable from pos, and let n be the length of nums. There are two base cases to check: if nums[pos] == 0, we will return pos, since we can’t leave position pos. And if pos == n-1 we will return n-1, since we can always get to the last position from itself. After the base cases, we check subproblems farthest(pos+1, nums) through farthest(pos+nums[pos], nums) stopping early if pos reaches the last element of nums.

So far, this is just a recursive solution, not a dynamic programming solution. To get acceptable performance, we will save each farthest result in an array dp of the same size as nums. When possible, we’ll look up the result in dp instead of calling farthest.

Implementation

Here’s a pseudocode implementation:

n = length of nums
define an array dp of size n
dp[n-1] = n-1  // if we get to the last position, we're done

if farthest(0, nums) >= n-1, return true
else return false

farthest(pos, nums)
    n = length of nums
    if nums[pos] == 0, update dp and return pos // base case
    if dp[pos] is defined, return dp[pos]       // memoization

    end = min(n-1, pos + nums[pos])  // stop if we get to the end
    for each i from pos+1 to end
        // update dp if we can get farther
        dp[pos] = max(dp[pos], farthest(i, nums))

    return dp[pos]

Reference

For a Java implementation with some optimizations and a preview of next week’s topic, see Prachi Sharma’s solution on LeetCode.

Thanks to Daniel Zingaro for suggesting an improvement to this article.

(Image credit: DALLĀ·E 3)

For an introduction to this year’s project, see A Project for 2024.

Categories: LeetCode

Prev
Next

Stay in the Know

I'm trying out the latest learning techniques on software development concepts, and writing about what works best. Sound interesting? Subscribe to my free newsletter to keep up to date. Learn More
Unsubscribing is easy, and I'll keep your email address private.

Getting Started

Are you new here? Check out my review posts for a tour of the archives:

  • 2023 in Review: 50 LeetCode Tips
  • 2022 in Review: Content Bots
  • 2021 in Review: Thoughts on Solving Programming Puzzles
  • Lessons from the 2020 LeetCode Monthly Challenges
  • 2019 in Review
  • Competitive Programming Frequently Asked Questions: 2018 In Review
  • What I Learned Working On Time Tortoise in 2017
  • 2016 in Review
  • 2015 in Review
  • 2015 Summer Review

Archives

Recent Posts

  • Do Coding Bots Mean the End of Coding Interviews? December 31, 2024
  • Another Project for 2024 May 8, 2024
  • Dynamic Programming Wrap-Up May 1, 2024
  • LeetCode 91: Decode Ways April 24, 2024
  • LeetCode 70: Climbing Stairs April 17, 2024
  • LeetCode 221: Maximal Square April 10, 2024
  • Using Dynamic Programming for Maximum Product Subarray April 3, 2024
  • LeetCode 62: Unique Paths March 27, 2024
  • LeetCode 416: Partition Equal Subset Sum March 20, 2024
  • LeetCode 1143: Longest Common Subsequence March 13, 2024
Red-Green-Code
  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter
Copyright © 2025 Duncan Smith