class Solution:
def fallingSquares(self, positions):
intervals = []
result = []
max_height = 0
for left, size in positions:
right = left + size
base = 0
for l, r, h in intervals:
if r > left and l < right:
base = max(base, h)
height = base + size
intervals.append((left, right, height))
max_height = max(max_height, height)
result.append(max_height)
return result
class Solution {
public:
vector<int> fallingSquares(vector<vector<int>>& positions) {
vector<tuple<int, int, int>> intervals;
vector<int> result;
int maxHeight = 0;
for (const auto& pos : positions) {
int left = pos[0], size = pos[1];
int right = left + size;
int base = 0;
for (const auto& interval : intervals) {
int l, r, h;
tie(l, r, h) = interval;
if (r > left && l < right) {
base = max(base, h);
}
}
int height = base + size;
intervals.emplace_back(left, right, height);
maxHeight = max(maxHeight, height);
result.push_back(maxHeight);
}
return result;
}
};
class Solution {
public List<Integer> fallingSquares(int[][] positions) {
List<int[]> intervals = new ArrayList<>();
List<Integer> result = new ArrayList<>();
int maxHeight = 0;
for (int[] pos : positions) {
int left = pos[0], size = pos[1], right = left + size;
int base = 0;
for (int[] interval : intervals) {
int l = interval[0], r = interval[1], h = interval[2];
if (r > left && l < right) {
base = Math.max(base, h);
}
}
int height = base + size;
intervals.add(new int[]{left, right, height});
maxHeight = Math.max(maxHeight, height);
result.add(maxHeight);
}
return result;
}
}
var fallingSquares = function(positions) {
let intervals = [];
let result = [];
let maxHeight = 0;
for (let [left, size] of positions) {
let right = left + size;
let base = 0;
for (let [l, r, h] of intervals) {
if (r > left && l < right) {
base = Math.max(base, h);
}
}
let height = base + size;
intervals.push([left, right, height]);
maxHeight = Math.max(maxHeight, height);
result.push(maxHeight);
}
return result;
};
The "Falling Squares" problem asks you to simulate dropping a sequence of squares onto a number line. Each square is described by a pair [left, size]
, meaning it starts at position left
and has a side length of size
. Each square falls straight down until it either lands on the ground (height zero) or on top of previous squares, stacking up if it overlaps with them.
After each square falls, you need to record the current maximum height of all stacked squares so far. The final output is a list of these heights after each drop.
positions
where each element is [left, size]
.At first glance, it might seem like you can just keep track of the heights of each square independently. However, since squares can overlap and stack, we have to consider all the intervals on the number line where heights change.
A brute-force approach would be to, for each new square, check all previous squares and see if their intervals overlap. If they do, the new square must stack on top of the highest one it overlaps with. This works, but as the number of squares grows, it becomes slow.
To optimize, we consider representing the current "skyline" as a set of intervals, each with a height. When a new square falls, we only need to find the maximum height in the overlapping region, then add the square on top of that. This reduces the problem to interval management and querying.
The main challenge is efficiently finding the maximum height for overlapping intervals and updating the intervals after each drop.
[left, right)
with a certain height.(left, right, height)
.left
and right
positions.base + size
.This straightforward approach is easy to implement and works well for moderate input sizes. For much larger inputs, segment trees or coordinate compression can further optimize the interval queries, but the above approach is sufficient for most practical cases.
Let's walk through an example with input positions = [[1, 2], [2, 3], [6, 1]]
.
The final output is [2, 5, 5]
.
For most interview or contest settings, the O(N^2) approach is acceptable unless N is very large.
The Falling Squares problem is a simulation of stacking blocks on a number line, requiring careful interval and height management. By modeling the skyline as a list of intervals and updating heights as each square falls, we can efficiently track the maximum stack height after each drop. The key insight is to check overlaps and stack on top of the highest overlapping interval, updating the result after each step. While optimizations exist for large input sizes, the basic approach is both intuitive and effective for most scenarios.