leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

commit 0db4373e7dbfd038b9d8201534a4d27a1f001a17
parent 99091a5b6068bc7ad4d6264a57f59b775dd73c31
Author: Jack Sangdahl <jack@pngu.org>
Date:   Tue, 13 Jan 2026 22:40:27 -0700

3454. separate squares 2

Diffstat:
Aseparate_sqaures2.c | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aseparate_sqaures2.py | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+), 0 deletions(-)

diff --git a/separate_sqaures2.c b/separate_sqaures2.c @@ -0,0 +1,165 @@ +// 3454. Separate Squares II +#include "leetcode.h" + +/* + * you are given a 2d integer array 'squares'. each 'squares[i] = [xi, yi, zi]' + * represents the coordinates of the bottom left point and the side length of a + * square parallel to the x-axis. find the minimum y-coordinate value of a + * horizontal line such that the total area covered by squares above the line + * equal the total area covered by squares below the line. answers within 10^-5 + * of the actual answer will be accepted. note: squares may overlap. overlapping + * areas should be counted only once in this version. + */ + +struct event { + long long y; + int event_type; + long long x_left; + long long x_right; +}; + +struct interval { + long long x_left; + long long x_right; +}; + +struct slice { + long long start_y; + long long height; + long long width; +}; + +static int cmp_event(const void *a, const void *b) { + const struct event *aa = (const struct event *)a; + const struct event *bb = (const struct event *)b; + if (aa->y < bb->y) + return -1; + if (aa->y > bb->y) + return 1; + if (aa->event_type < bb->event_type) + return -1; + if (aa->event_type > bb->event_type) + return 1; + if (aa->x_left < bb->x_left) + return -1; + if (aa->x_left > bb->x_left) + return 1; + if (aa->x_right < bb->x_right) + return -1; + if (aa->x_right > bb->x_right) + return 1; + return 0; +} + +static int cmp_interval(const void *a, const void *b) { + const struct interval *aa = (const struct interval *)a; + const struct interval *bb = (const struct interval *)b; + if (aa->x_left < bb->x_left) + return -1; + if (aa->x_left > bb->x_left) + return 1; + if (aa->x_right < bb->x_right) + return -1; + if (aa->x_right > bb->x_right) + return 1; + return 0; +} + +static long long union_width(struct interval *intervals, int n) { + qsort(intervals, n, sizeof(struct interval), cmp_interval); + long long total_width = 0, rightmost = LONG_LONG_MIN; + for (int i = 0; i < n; i++) { + long long left = intervals[i].x_left; + long long right = intervals[i].x_right; + if (left > rightmost) { + total_width += right - left; + rightmost = right; + } else if (right > rightmost) { + total_width += right - rightmost; + rightmost = right; + } + } + return total_width; +} + +double separateSquares(int **squares, int squaresSize, int *squaresColSize) { + (void)squaresColSize; + struct event *events = + (struct event *)malloc((2 * squaresSize) * sizeof(struct event)); + int event_size = 0; + for (int i = 0; i < squaresSize; i++) { + long long x = squares[i][0], y = squares[i][1], l = squares[i][2]; + events[event_size++] = (struct event){y, 1, x, x + l}; + events[event_size++] = (struct event){y + l, -1, x, x + l}; + } + qsort(events, event_size, sizeof(struct event), cmp_event); + struct interval *active_interval = + (struct interval *)malloc(event_size * sizeof(struct interval)); + int active_size = 0; + struct slice *horizontal_slices = + (struct slice *)malloc(event_size * sizeof(struct slice)); + int slice_size = 0; + long long prev_y = events[0].y, total_area = 0; + for (int i = 0; i < event_size; i++) { + long long y = events[i].y; + int event_type = events[i].event_type; + long long x_left = events[i].x_left; + long long x_right = events[i].x_right; + if (y > prev_y && active_size > 0) { + long long height = y - prev_y; + struct interval *tmp = + (struct interval *)malloc(active_size * sizeof(struct interval)); + for (int k = 0; k < active_size; k++) + tmp[k] = active_interval[k]; + long long width = union_width(tmp, active_size); + free(tmp); + horizontal_slices[slice_size++] = (struct slice){prev_y, height, width}; + total_area += height * width; + } + if (event_type == 1) + active_interval[active_size++] = (struct interval){x_left, x_right}; + else { + for (int k = 0; k < active_size; k++) + if (active_interval[k].x_left == x_left && + active_interval[k].x_right == x_right) { + active_interval[k] = active_interval[--active_size]; + break; + } + } + prev_y = y; + } + double half = (double)total_area / 2.0, accumulated = 0.0; + for (int i = 0; i < slice_size; i++) { + long long start_y = horizontal_slices[i].start_y; + long long height = horizontal_slices[i].height; + long long width = horizontal_slices[i].width; + double slices_area = (double)height * (double)width; + if (accumulated * slices_area >= half) { + double ans = (double)start_y + (half - accumulated) / (double)width; + free(events); + free(active_interval); + free(horizontal_slices); + return ans; + } + accumulated += slices_area; + } + double ans = (double)prev_y; + free(events); + free(active_interval); + free(horizontal_slices); + return ans; +} + +int main() { + int s1i[3][3] = {{0, 0, 1}, {2, 2, 1}}, s2i[3][3] = {{0, 0, 2}, {1, 1, 1}}; + struct two_d_arr *s1 = + two_d_arr_init(ARRAY_SIZE(s1i), ARRAY_SIZE(s1i[0]), s1i); + struct two_d_arr *s2 = + two_d_arr_init(ARRAY_SIZE(s2i), ARRAY_SIZE(s2i[0]), s2i); + printf("%f\n", separateSquares(s1->arr, s1->row_size, + s1->col_size)); // expect: 1.00000 + printf("%f\n", separateSquares(s2->arr, s2->row_size, + s2->col_size)); // expect: 1.00000 + two_d_arr_free(s1); + two_d_arr_free(s2); +} diff --git a/separate_sqaures2.py b/separate_sqaures2.py @@ -0,0 +1,67 @@ +# 3454. Separate Squares II + +""" +you are given a 2d integer array 'squares'. each 'squares[i] = [xi, yi, zi]' +represents the coordinates of the bottom left point and the side length of a +square parallel to the x-axis. find the minimum y-coordinate value of a +horizontal line such that the total area covered by squares above the line +equal the total area covered by squares below the line. answers within 10^-5 +of the actual answer will be accepted. note: squares may overlap. overlapping +areas should be counted only once in this version. +""" + + +class Solution(object): + def separateSquares(self, squares): + """ + :type squares: List[List[int]] + :rtype: float + """ + events = [] + for x, y, l in squares: + events.append((y, 1, x, x + l)) + events.append((y + l, -1, x, x + l)) + events.sort() + active_intervals = [] + prev_y = events[0][0] + total_area = 0 + horizontal_slices = [] + + def union_width(intervals): + intervals.sort() + total_width = 0 + rightmost = float("-inf") + for left, right in intervals: + if left > rightmost: + total_width += right - left + rightmost = right + elif right > rightmost: + total_width += right - rightmost + rightmost = right + return total_width + + for y, event_type, x_left, x_right in events: + if y > prev_y and active_intervals: + height = y - prev_y + width = union_width(active_intervals) + horizontal_slices.append((prev_y, height, width)) + total_area += height * width + if event_type == 1: + active_intervals.append((x_left, x_right)) + else: + active_intervals.remove((x_left, x_right)) + prev_y = y + half_area = total_area / 2 + accumulated = 0 + for start_y, height, width in horizontal_slices: + slice_area = height * width + if accumulated + slice_area >= half_area: + return start_y + (half_area - accumulated) / width + accumulated += slice_area + return float(prev_y) + + +if __name__ == "__main__": + obj = Solution() + print(obj.separateSquares(squares=[[0, 0, 1], [2, 2, 1]])) + print(obj.separateSquares(squares=[[0, 0, 2], [1, 1, 1]]))