Skip to content

Commit 3e8540b

Browse files
committedJul 10, 2018
Add Jump Game.
1 parent 5497597 commit 3e8540b

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed
 

‎README.md

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ a set of rules that precisely define a sequence of operations.
116116
* **Uncategorized**
117117
* `B` [Tower of Hanoi](src/algorithms/uncategorized/hanoi-tower)
118118
* `B` [Square Matrix Rotation](src/algorithms/uncategorized/square-matrix-rotation) - in-place algorithm
119+
* `B` [Jump Game](src/algorithms/uncategorized/jump-game) - backtracking, dynamic programming (top-down + bottom-up) and greedy examples
119120
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
120121
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)
121122

@@ -129,6 +130,7 @@ algorithm is an abstraction higher than a computer program.
129130
* `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray)
130131
* `A` [Travelling Salesman Problem](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city
131132
* **Greedy** - choose the best option at the current time, without any consideration for the future
133+
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
132134
* `A` [Unbound Knapsack Problem](src/algorithms/sets/knapsack-problem)
133135
* `A` [Dijkstra Algorithm](src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices
134136
* `A` [Prim’s Algorithm](src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph
@@ -142,10 +144,12 @@ algorithm is an abstraction higher than a computer program.
142144
* `B` [Quicksort](src/algorithms/sorting/quick-sort)
143145
* `B` [Tree Depth-First Search](src/algorithms/tree/depth-first-search) (DFS)
144146
* `B` [Graph Depth-First Search](src/algorithms/graph/depth-first-search) (DFS)
147+
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
145148
* `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions)
146149
* `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions)
147150
* **Dynamic Programming** - build up a solution using previously found sub-solutions
148151
* `B` [Fibonacci Number](src/algorithms/math/fibonacci)
152+
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
149153
* `A` [Levenshtein Distance](src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
150154
* `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS)
151155
* `A` [Longest Common Substring](src/algorithms/string/longest-common-substring)
@@ -159,6 +163,7 @@ algorithm is an abstraction higher than a computer program.
159163
* **Backtracking** - similarly to brute force, try to generate all possible solutions, but each time you generate next solution you test
160164
if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a
161165
different path of finding a solution. Normally the DFS traversal of state-space is being used.
166+
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
162167
* `A` [Hamiltonian Cycle](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once
163168
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
164169
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Jump Game
2+
3+
## The Problem
4+
5+
Given an array of non-negative integers, you are initially positioned at
6+
the first index of the array. Each element in the array represents your maximum
7+
jump length at that position.
8+
9+
Determine if you are able to reach the last index.
10+
11+
**Example #1**
12+
13+
```
14+
Input: [2,3,1,1,4]
15+
Output: true
16+
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
17+
```
18+
19+
**Example #2**
20+
21+
```
22+
Input: [3,2,1,0,4]
23+
Output: false
24+
Explanation: You will always arrive at index 3 no matter what. Its maximum
25+
jump length is 0, which makes it impossible to reach the last index.
26+
```
27+
28+
## Naming
29+
30+
We call a position in the array a **"good index"** if starting at that position,
31+
we can reach the last index. Otherwise, that index is called a **"bad index"**.
32+
The problem then reduces to whether or not index 0 is a "good index".
33+
34+
## Solutions
35+
36+
### Approach 1: Backtracking
37+
38+
This is the inefficient solution where we try every single jump pattern that
39+
takes us from the first position to the last. We start from the first position
40+
and jump to every index that is reachable. We repeat the process until last
41+
index is reached. When stuck, backtrack.
42+
43+
> See [backtrackingJumpGame.js](backtrackingJumpGame.js) file
44+
45+
**Time complexity:**: `O(2^n)`.
46+
There are 2<sup>n</sup> (upper bound) ways of jumping from
47+
the first position to the last, where `n` is the length of
48+
array `nums`.
49+
50+
**Auxiliary Space Complexity**: `O(n)`.
51+
Recursion requires additional memory for the stack frames.
52+
53+
### Approach 2: Dynamic Programming Top-down
54+
55+
Top-down Dynamic Programming can be thought of as optimized
56+
backtracking. It relies on the observation that once we determine
57+
that a certain index is good / bad, this result will never change.
58+
This means that we can store the result and not need to recompute
59+
it every time.
60+
61+
Therefore, for each position in the array, we remember whether the
62+
index is good or bad. Let's call this array memo and let its values
63+
be either one of: GOOD, BAD, UNKNOWN. This technique is
64+
called memoization.
65+
66+
> See [dpTopDownJumpGame.js](dpTopDownJumpGame.js) file
67+
68+
**Time complexity:**: `O(n^2)`.
69+
For every element in the array, say `i`, we are looking at the
70+
next `nums[i]` elements to its right aiming to find a GOOD
71+
index. `nums[i]` can be at most `n`, where `n` is the length
72+
of array `nums`.
73+
74+
**Auxiliary Space Complexity**: `O(2 * n) = O(n)`.
75+
First `n` originates from recursion. Second `n` comes from the
76+
usage of the memo table.
77+
78+
### Approach 3: Dynamic Programming Bottom-up
79+
80+
Top-down to bottom-up conversion is done by eliminating recursion.
81+
In practice, this achieves better performance as we no longer have the
82+
method stack overhead and might even benefit from some caching. More
83+
importantly, this step opens up possibilities for future optimization.
84+
The recursion is usually eliminated by trying to reverse the order of
85+
the steps from the top-down approach.
86+
87+
The observation to make here is that we only ever jump to the right.
88+
This means that if we start from the right of the array, every time
89+
we will query a position to our right, that position has already be
90+
determined as being GOOD or BAD. This means we don't need to recurse
91+
anymore, as we will always hit the memo table.
92+
93+
> See [dpBottomUpJumpGame.js](dpBottomUpJumpGame.js) file
94+
95+
**Time complexity:**: `O(n^2)`.
96+
For every element in the array, say `i`, we are looking at the
97+
next `nums[i]` elements to its right aiming to find a GOOD
98+
index. `nums[i]` can be at most `n`, where `n` is the length
99+
of array `nums`.
100+
101+
**Auxiliary Space Complexity**: `O(n)`.
102+
This comes from the usage of the memo table.
103+
104+
### Approach 4: Greedy
105+
106+
Once we have our code in the bottom-up state, we can make one final,
107+
important observation. From a given position, when we try to see if
108+
we can jump to a GOOD position, we only ever use one - the first one.
109+
In other words, the left-most one. If we keep track of this left-most
110+
GOOD position as a separate variable, we can avoid searching for it in
111+
the array. Not only that, but we can stop using the array altogether.
112+
113+
> See [greedyJumpGame.js](greedyJumpGame.js) file
114+
115+
**Time complexity:**: `O(n)`.
116+
We are doing a single pass through the `nums` array, hence `n` steps,
117+
where `n` is the length of array `nums`.
118+
119+
**Auxiliary Space Complexity**: `O(1)`.
120+
We are not using any extra memory.
121+
122+
## References
123+
124+
- [Jump Game Fully Explained on LeetCode](https://leetcode.com/articles/jump-game/)
125+
- [Dynamic Programming vs Divide and Conquer](https://itnext.io/dynamic-programming-vs-divide-and-conquer-2fea680becbe)
126+
- [Dynamic Programming](https://en.wikipedia.org/wiki/Dynamic_programming)
127+
- [Memoization on Wikipedia](https://en.wikipedia.org/wiki/Memoization)
128+
- [Top-Down and Bottom-Up Design on Wikipedia](https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design)

0 commit comments

Comments
 (0)
Please sign in to comment.