Falling Squares - Complete Solution Guide
Falling Squares is LeetCode problem 699, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
There are several squares being dropped onto the X-axis of a 2D plane. You are given a 2D integer array positions where positions[i] = [left i , sideLength i ] represents the i th square with a side length of sideLength i that is dropped with its left edge aligned with X-coordinate left i . Each square is dropped one at a time from a height above any landed squares. It then falls downward (negative Y direction) until it either lands on the top side of another square or on the X-axis . A square b
Detailed Explanation
The Falling Squares problem involves dropping squares onto the X-axis. Each square is defined by its leftmost X-coordinate and its side length. Squares fall until they hit either the X-axis or another square. The goal is to determine the maximum height of the stack of squares after each square is dropped and return a list containing these heights.
Solution Approach
The solution employs a Segment Tree with Lazy Propagation to efficiently track the maximum height within any given range on the X-axis. Coordinate compression is used to handle large X-coordinate values. After dropping each square, the algorithm queries the segment tree to find the maximum height within the range covered by the new square, adds the side length of the new square to that height, updates the segment tree with the new height for that range, and then records the maximum height encountered so far.
Step-by-Step Algorithm
- Step 1: Collect all X-coordinates (left and right edges) of all squares.
- Step 2: Sort the collected X-coordinates and remove duplicates to perform coordinate compression. This maps the X-coordinates to indices in a smaller range.
- Step 3: Build a segment tree with lazy propagation. The segment tree stores the maximum height in each range of compressed coordinates.
- Step 4: Iterate through each square:
- Step 5: For each square, query the segment tree for the maximum height in the range [left_index, right_index], where the indices are based on compressed coordinates.
- Step 6: Calculate the new height by adding the side length of the current square to the maximum height found in the previous step.
- Step 7: Update the segment tree with the new height for the range [left_index, right_index].
- Step 8: Update the global maximum height if the new height exceeds the current global maximum.
- Step 9: Store the global maximum height in the answer list.
- Step 10: Return the answer list.
Key Insights
- Insight 1: The crucial realization is that only the 'landing' of the square matters, not the intermediate falling process. We only care about the height of the existing squares in the interval covered by the new square.
- Insight 2: The X-coordinates can be large, but the number of squares is limited. We can use coordinate compression to map these large X-coordinates to smaller indices to efficiently use data structures like segment trees.
- Insight 3: A Segment Tree with Lazy Propagation is the right data structure. Because we update ranges of coordinates with a new height, the lazy propagation optimizes the update operation.
Complexity Analysis
Time Complexity: O(n log n)
Space Complexity: O(n)
Topics
This problem involves: Array, Segment Tree, Ordered Set.
Companies
Asked at: Block.