There is a long and thin painting that can be represented by a number line. The painting was painted with multiple overlapping segments where each segment was painted with a unique color. You are given a 2D integer array segments
, where segments[i] = [starti, endi, colori]
represents the half-closed segment [starti, endi)
with colori
as the color.
The colors in the overlapping segments of the painting were mixed when it was painted. When two or more colors mix, they form a new color that can be represented as a set of mixed colors.
2
, 4
, and 6
are mixed, then the resulting mixed color is {2,4,6}
.For the sake of simplicity, you should only output the sum of the elements in the set rather than the full set.
You want to describe the painting with the minimum number of non-overlapping half-closed segments of these mixed colors. These segments can be represented by the 2D array painting
where painting[j] = [leftj, rightj, mixj]
describes a half-closed segment [leftj, rightj)
with the mixed color sum of mixj
.
segments = [[1,4,5],[1,7,7]]
can be described by painting = [[1,4,12],[4,7,7]]
because:
[1,4)
is colored {5,7}
(with a sum of 12
) from both the first and second segments.[4,7)
is colored {7}
from only the second segment.Return the 2D array painting
describing the finished painting (excluding any parts that are not painted). You may return the segments in any order.
A half-closed segment [a, b)
is the section of the number line between points a
and b
including point a
and not including point b
.
Example 1:
Input: segments = [[1,4,5],[4,7,7],[1,7,9]] Output: [[1,4,14],[4,7,16]] Explanation: The painting can be described as follows: - [1,4) is colored {5,9} (with a sum of 14) from the first and third segments. - [4,7) is colored {7,9} (with a sum of 16) from the second and third segments.
Example 2:
Input: segments = [[1,7,9],[6,8,15],[8,10,7]] Output: [[1,6,9],[6,7,24],[7,8,15],[8,10,7]] Explanation: The painting can be described as follows: - [1,6) is colored 9 from the first segment. - [6,7) is colored {9,15} (with a sum of 24) from the first and second segments. - [7,8) is colored 15 from the second segment. - [8,10) is colored 7 from the third segment.
Example 3:
Input: segments = [[1,4,5],[1,4,7],[4,7,1],[4,7,11]] Output: [[1,4,12],[4,7,12]] Explanation: The painting can be described as follows: - [1,4) is colored {5,7} (with a sum of 12) from the first and second segments. - [4,7) is colored {1,11} (with a sum of 12) from the third and fourth segments. Note that returning a single segment [1,7) is incorrect because the mixed color sets are different.
Constraints:
1 <= segments.length <= 2 * 104
segments[i].length == 3
1 <= starti < endi <= 105
1 <= colori <= 109
colori
is distinct.This problem involves processing a series of painting segments to determine the final painted result. Each segment has a start, end, and color. Overlapping segments mix their colors, and we need to represent the final painting using the minimum number of non-overlapping segments. The solution uses a line sweep algorithm with a TreeMap
(or equivalent sorted map) to efficiently track color changes along the number line.
Algorithm:
Event Tracking: We use a map to store events at each point on the number line. The keys represent the coordinates (start and end points of segments), and the values represent the change in the sum of colors at that coordinate. For each segment [start, end, color]
, we add color
to the event at start
and subtract color
from the event at end
. This technique effectively captures the color additions and removals at each point.
Sorting Events: We sort the events by coordinate. This ensures we process the number line from left to right.
Prefix Sum: We perform a prefix sum on the sorted events. This means we accumulate the changes in color sums to get the total color sum at each point.
Outputting Segments: We iterate through the sorted events. When the cumulative color sum is greater than 0, it means that section is painted. We record the start of this painted section. When the cumulative color sum returns to 0, it indicates the end of a painted section; we then create a new segment using the start and end points we've recorded, along with the cumulative color sum.
Time and Space Complexity:
Time Complexity: O(N log N), dominated by sorting the events (where N is the number of segments). The prefix sum calculation and iteration through the sorted events take linear time.
Space Complexity: O(N), proportional to the number of unique coordinates on the number line that are either starts or ends of segments. In the worst-case scenario, each segment could have a unique start and end point.
Code Explanation (Python):
from collections import defaultdict
class Solution:
def splitPainting(self, segments: List[List[int]]) -> List[List[int]]:
d = defaultdict(int) # Map to store events at each coordinate
for l, r, c in segments:
d[l] += c # Add color at start
d[r] -= c # Subtract color at end
s = sorted([[k, v] for k, v in d.items()]) # Sort events by coordinate
n = len(s)
for i in range(1, n): #Prefix sum calculation
s[i][1] += s[i - 1][1]
result = []
for i in range(n - 1): # Iterate through sorted events
if s[i][1] > 0: # Check if section is painted
result.append([s[i][0], s[i + 1][0], s[i][1]]) #Create segment
return result
The Java and C++ codes follow the same logic, using TreeMap
and map
respectively for efficient sorted storage of events. The core idea is the same across all languages. The prefix sum is implicitly calculated during the iteration in the Java and C++ solutions because the TreeMap
/ map
already keeps the events sorted.