Problem overview
The method jump receives nums, an Array[Int] of non-negative integers. You start at index 0, and nums(i) is the farthest you can jump forward from index i. The method returns the minimum number of jumps needed to land on the last index.
For [2, 3, 1, 1, 4] the answer is 2: jump one step from index 0 to index 1, then three steps to index 4. A single jump from index 0 reaches at most index 2, so one jump is not enough.
Approach: grow the reach one jump at a time
A brute-force search would try every jump length from every index, and the number of paths grows quickly. The greedy idea avoids that by thinking in rounds. After k jumps there is a set of indices you could be standing on, and that set is always a block of consecutive indices from 0 up to some farthest index. You never need to track which exact index you're on, only how far the block reaches.
The solution keeps two numbers:
curMax: the farthest index reachable with the jumps counted so far;nextMax: the farthest index reachable with one more jump, starting from any index seen so far.
The scan walks index by index. While i is still within curMax, the current jumps are enough to get there. Every index also updates nextMax with i + nums(i). When the scan reaches an index beyond curMax, one more jump is unavoidable. That jump starts from whichever earlier index reaches farthest, which is exactly what nextMax remembers, so curMax becomes nextMax.
Trace [2, 3, 1, 1, 4]. Start with result = 1, curMax = 2 and nextMax = 2:
- Index 1: it is within reach (2 >= 1).
nextMaxbecomesmax(2, 1 + 3) = 4. - Index 2: within reach.
nextMaxstays 4. - Index 3: beyond
curMax(2 < 3). Count a second jump,result = 2, and setcurMax = 4. ThennextMaxstays 4. - Index 4: within reach (4 >= 4).
nextMaxbecomes 8, which no longer matters.
The method returns 2.
Step by step
- Handle the trivial case. With one index or none, you're already on the last index, so return 0.
- Start
resultat 1. With at least two indices you need at least one jump, so that first jump is counted right away. - Set
curMaxtonums(0). The first jump can take you as far as the first element allows. - Set
nextMaxtonums(0)too. Index 0 is the only index seen so far, so it is the only starting point for a second jump. - Loop over
1 until nums.length. This visits every index after the first, once each. The range excludes its end. - Check whether index
iis out of reach (curMax < i). If so, add a jump toresultand setcurMaxtonextMax. - Update
nextMaxfor every index withmath.max(nextMax, i + nums(i)). This runs even for the index that just triggered a jump, because that index can be where the following jump starts. - End with
resultas the last expression, which Scala returns withoutreturn.
The solution in Scala
class Solution {
def jump(nums: Array[Int]): Int = {
if (nums.length <= 1) {
return 0
}
var result = 1
var curMax = nums(0)
var nextMax = nums(0)
for (i <- 1 until nums.length) {
if (curMax < i) {
result += 1
curMax = nextMax
}
nextMax = math.max(nextMax, i + nums(i))
}
result
}
}
The Scala details worth a closer look:
returnand last expressions. The earlyreturn 0is allowed in a method body. The finalresulthas noreturnbecause the last expression of a block is its value.untilversusto.1 until nums.lengthstops before the length, which is the last valid index plus one.1 to nums.lengthwould include the length and fail with anArrayIndexOutOfBoundsException.- Parameters are
vals. You can't reassignnums, which is why the changing values live in their ownvars. - Arrays use parentheses.
nums(i)is a method call on the array, not a bracket index.
Complexity
Time: O(n). The loop visits each index once and does a constant amount of work for each.
Space: O(1). The solution keeps three integers and the loop index, whatever the size of the input.
Edge cases and common mistakes
- One element.
[0]returns 0, because you start on the last index. An empty array returns 0 too. - A single big jump.
[5, 1, 1, 1, 1]returns 1. The first jump already reaches past the end, socurMaxis never smaller thani. - Steps of one.
[1, 1, 1, 1]returns 3, one jump per step. - Zeros you can jump over.
[2, 0, 1]returns 1: the first jump lands on the last index directly and never touches the 0. - Unreachable ends. The method assumes the last index can be reached. For
[1, 0, 3]it returns 2 even though no sequence of jumps gets past the 0, so it doesn't report impossibility. A version that must handle such inputs needs an extra check oncurMaxandnextMax. - Forgetting the starting jump. Starting
resultat 0 undercounts every input of two or more elements by one. - Skipping the
nextMaxupdate on the index that triggers a jump. That index can start the next jump, so leaving it out can make later jumps too short.
Testing
[2, 3, 1, 1, 4]gives2.[0]gives0.[1, 1, 1, 1]gives3.[5, 1, 1, 1, 1]gives1.[2, 0, 1]gives1.
