TL;DR
Running prefix sum, track the max β O(n) time, O(1) space.
Approach 1 β Brute force
Compute each visited altitude independently: the altitude after leg i is the sum of the first i + 1 gains, so re-sum that prefix from scratch for every i and take the maximum (seeding with the starting altitude 0).
from typing import List
class Solution:
def largestAltitude(self, gain: List[int]) -> int:
best = 0 # the starting altitude counts
for i in range(len(gain)):
altitude = sum(gain[:i + 1])
best = max(best, altitude)
return best
Complexity: O(n^2) time (prefix i costs i + 1 additions), O(n) space for the slices. With n <= 100 it actually passes β the constraints donβt kill it β but it redoes work that grows quadratically and would collapse at realistic sizes.
Approach 2 β Running prefix sum
The insight: consecutive altitudes overlap almost entirely β altitude i is just altitude i - 1 plus gain[i]. This is the prefix sum technique in its streaming form: carry one running total instead of re-summing, and fold the max into the same pass.
from typing import List
class Solution:
def largestAltitude(self, gain: List[int]) -> int:
best = 0
altitude = 0
for g in gain:
altitude += g
best = max(best, altitude)
return best
Walkthrough on gain = [-5,1,5,0,-7]:
| g | altitude | best |
|---|
| β (start) | 0 | 0 |
| -5 | -5 | 0 |
| 1 | -4 | 0 |
| 5 | 1 | 1 |
| 0 | 1 | 1 |
| -7 | -6 | 1 |
Return 1, matching the example. On [-4,-3,-2,-1,4,3,2] the running altitude never rises above 0, so best stays at its seed and the answer is 0.
Complexity: O(n) time, O(1) extra space.
The insight: the sequence of altitudes is the sequence of prefix sums, and Python ships a generator for exactly that β itertools.accumulate. Expressing the loop as max over accumulate makes the intent (βhighest prefix sum, floored by the startβ) read directly.
from itertools import accumulate
from typing import List
class Solution:
def largestAltitude(self, gain: List[int]) -> int:
return max(0, max(accumulate(gain)))
Walkthrough on gain = [2,2,-3,4]:
accumulate(gain) yields 2, 4, 1, 5 β the altitudes after each leg.
- Inner
max β 5; outer max(0, 5) β 5 (the outer max is what re-admits the starting altitude, which matters when all prefixes are negative).
Complexity: O(n) time, O(1) extra space (accumulate is lazy). Same asymptotics as Approach 2 β this is the idiomatic-Python spelling of the identical algorithm.
Common pitfalls
- Forgetting that the starting altitude
0 counts: with all-negative prefixes (example 2) the answer is 0, not the largest prefix sum. Seed best = 0 or wrap with max(0, ...).
- Returning the final altitude instead of the maximum altitude β the cyclist may peak mid-trip and descend.
- Comparing
best before adding g (or after, inconsistently) β update the altitude first, then compare, or you evaluate each legβs starting point twice and its endpoint never.
- Reading
gain[i] as the altitude at point i rather than the change during leg i β the array is deltas, not positions.
Pattern takeaway
βSequence of deltas, question about positionsβ means prefix sums: one running accumulator turns every position query into O(1) incremental work. Fold whatever aggregate the problem asks for (here a max, elsewhere a count or a hash-map lookup of earlier prefix values) into the same single pass β this is the same running-prefix skeleton that powers Find Pivot Index and subarray-sum problems.