Logo for ammarahmed.ca
Medium
Jan 13, 2026
#heap

Skyscraper Furthest Distance

A player needs to traverse between skyscrapers, carrying springs and sandbags. The heights of these buildings vary.

If the next building's rooftop is lower than or equal to the current one, the player can move freely.

If the next rooftop is higher, the player must either:

  • Use sandbags (each sandbag increases the player's height by 1; if the sum of the current height and sandbags equals the next rooftop's height, the player can move forward).
    • Use springs to jump directly to the next rooftop, regardless of height difference.

      The goal is to determine the index of how far the player can travel.

      Example 1:

      1Input: heights = [2, 3, 5, 1, 7], springs = 1, sandbags = 2 2Output: 3 3Explanation: Use 1 sandbag to move from 2 -> 3, use 1 spring to move from 3 -> 5, 5 -> 1 is a free move. Cannot move further, therefore, index 3.

      Example 2:

      1Input: heights = [4, 2, 2, 6, 3, 7], springs = 1, sandbags = 4 2Output: 5 3Explanation: 4 -> 2 free, 2 -> 2 free, 2 -> 6 use 4 sandbags, 6 -> 3 free, 3 -> 7, need 4 sandbags, use spring. Can also use spring at 2 -> 6 instead, same result

      Example 3:

      1Input: heights = [1, 5, 2, 3, 10], springs = 1, sandbags = 3 2Output: 3 3Explanation: 1 -> 5 must use spring, 5 -> 2 free, 2 -> 3 use 1 sandbag, 3 -> 10 need 7 sandbags or 1 spring, don't have either, return 3

      Notes

      Intuition

      Springs are most valuable for the largest height differences. Use sandbags first, and when you run out, retroactively convert the largest sandbag usage to a spring.

      Implementation

      Use a max heap to track height differences. For each upward jump, subtract from sandbags and add the difference to the heap. If sandbags go negative and no springs remain, return the current index. Otherwise, use a spring by popping the largest jump from the heap and adding those sandbags back. Continue until the end.

      Edge-cases

      Python's heapq is a min heap—negate values to simulate max heap behavior. Remember to negate again when popping.

      • Time: O(n log n) — heap operations for each building
        • Space: O(n) — heap stores jump sizes

          Complexity

          Solution

          1from typing import List 2import heapq 3 4class Solution: 5 def furthestDistance(self, heights: List[int], springs: int, sandbags: int) -> int: 6 # Optimal (min heap, O(n log n) time, O(n) space) 7 max_heap = [] 8 # O(n) 9 for i in range(len(heights) - 1): 10 diff = heights[i + 1] - heights[i] 11 if diff <= 0: 12 continue 13 14 sandbags -= diff 15 # O(log n) 16 heapq.heappush(max_heap, -diff) 17 18 if sandbags < 0: 19 if springs == 0: 20 return i 21 springs -= 1 22 # O(log n) 23 sandbags += -heapq.heappop(max_heap) 24 return len(heights) - 1 25 26if __name__ == "__main__": 27 # Include one-off tests here or debugging logic that can be run by running this file 28 # e.g. print(solution.two_sum([1, 2, 3, 4], 3)) 29 solution = Solution() 30