列表

详情


LCP 37. 最小矩形面积

二维平面上有 $N$ 条直线,形式为 y = kx + b,其中 kb为整数 且 k > 0。所有直线以 [k,b] 的形式存于二维数组 lines 中,不存在重合的两条直线。两两直线之间可能存在一个交点,最多会有 $C_N^2$ 个交点。我们用一个平行于坐标轴的矩形覆盖所有的交点,请问这个矩形最小面积是多少。若直线之间无交点、仅有一个交点或所有交点均在同一条平行坐标轴的直线上,则返回0。

注意:返回结果是浮点数,与标准答案 绝对误差或相对误差 在 10^-4 以内的结果都被视为正确结果

示例 1:

输入:lines = [[2,3],[3,0],[4,1]]

输出:48.00000

解释:三条直线的三个交点为 (3, 9) (1, 5) 和 (-1, -3)。最小覆盖矩形左下角为 (-1, -3) 右上角为 (3,9),面积为 48

示例 2:

输入:lines = [[1,1],[2,3]]

输出:0.00000

解释:仅有一个交点 (-2,-1)

限制:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: double minRecSize(vector<vector<int>>& lines) { } };

python3 解法, 执行用时: 308 ms, 内存消耗: 43.9 MB, 提交时间: 2023-07-19 18:05:44

'''
数学推导用k,b表示交点的横纵坐标找规律,求解交点横纵坐标的最大最小值然后进行求解。
'''
class Solution:
    def minRecSize(self, lines: List[List[int]]) -> float:
        lines.sort()
        count, i, top = [[0]*3 for i in range(10000)], 0, 0
        count[0][0], count[0][1] = lines[0][0], 0
        for i in range(1, len(lines)):
            if lines[i][0] != lines[i-1][0]:
                count[top][2] = i-1
                top += 1
                count[top][0] = lines[i][0]
                count[top][1] = i
        count[top][2] = len(lines) - 1
        if top == 0:
            return 0
        max_x = (lines[count[0][2]][1] - lines[count[1][1]][1])/(count[1][0] - count[0][0])
        min_x = (lines[count[0][1]][1] - lines[count[1][2]][1])/(count[1][0] - count[0][0])
        for i in range(1, top):
            max_x = max(max_x, (lines[count[i][2]][1] - lines[count[i+1][1]][1])/(count[i+1][0] - count[i][0]))
            min_x = min(min_x, (lines[count[i][1]][1] - lines[count[i+1][2]][1])/(count[i+1][0] - count[i][0]))

        
        max_y = (lines[count[0][2]][1]* count[1][0] - lines[count[1][1]][1]* count[0][0])/(count[1][0] - count[0][0])
        min_y = (lines[count[0][1]][1]* count[1][0] - lines[count[1][2]][1]* count[0][0])/(count[1][0] - count[0][0])
        for i in range(1,top):
            max_y = max(max_y, (lines[count[i][2]][1]* count[i+1][0] - lines[count[i+1][1]][1]* count[i][0])/(count[i+1][0] - count[i][0]))
            min_y = min(min_y, (lines[count[i][1]][1]* count[i+1][0] - lines[count[i+1][2]][1]* count[i][0])/(count[i+1][0] - count[i][0]))

        return (max_x - min_x) * (max_y - min_y)

python3 解法, 执行用时: 156 ms, 内存消耗: 44.5 MB, 提交时间: 2023-07-19 18:04:38

'''
考虑左下方无限远处,这时再往远走,所有直线之间的距离会越来越远,不会再有交点。
而慢慢靠近原点,最先出现交点的必是相邻两条直线。
'''
from collections import defaultdict
class Solution:
    def minRecSize(self, lines: List[List[int]]) -> float:
        d=defaultdict(list)
        for line in lines:
            d[line[0]].append(line[1])
        
        xs,ys=[],[]
        def intersect(f,g):
            xs.append(x:=(g[1]-f[1])/(f[0]-g[0]))
            ys.append(y:=f[0]*x+f[1])
        
        k=sorted(d.keys())
        for i,j in zip(k[:-1],k[1:]) :
            intersect((i,min(d[i])),(j,max(d[j])))
            intersect((i,max(d[i])),(j,min(d[j])))
        return (max(xs)-min(xs))*(max(ys)-min(ys)) if xs else 0

cpp 解法, 执行用时: 284 ms, 内存消耗: 66.2 MB, 提交时间: 2023-07-19 18:02:03

/**
 * 按(k, b)分类排序后,只有相邻两列的最上、最下两个顶点之间的连线才有可能构成答案
 * 
 **/
class Solution {
public:
    double minRecSize(vector<vector<int>>& f) {
        int n = f.size();
        vector<int> k(n, 0), b(n, 0);
        sort(f.begin(), f.end());
        for (int i = 0; i < n; i++) {
            k[i] = f[i][0]; b[i] = f[i][1];
        }
        int p = 0, q = 0;
        while (q < n && k[q] == k[p]) q++;
        if (q >= n) return 0.;
        double x_min = 1e100, x_max = -1e100;
        double y_min = 1e100, y_max = -1e100;
        for (; q < n;) {
            int r = q;
            while (r + 1 < n && k[r + 1] == k[q]) r++;
            // [p, q - 1], [q, r]
            double cx1 = 1.0 * (b[r] - b[p]) / (k[r] - k[p]);
            double cx2 = 1.0 * (b[q] - b[q - 1]) / (k[q] - k[q - 1]);
            x_min = min(x_min, min(cx1, cx2));
            x_max = max(x_max, max(cx1, cx2));
            double cy1 = 1.0 * (b[r] * k[p] - b[p] * k[r]) / (k[r] - k[p]);
            double cy2 = 1.0 * (b[q] * k[q - 1] - b[q - 1] * k[q]) / (k[q] - k[q - 1]);
            y_min = min(y_min, min(cy1, cy2));
            y_max = max(y_max, max(cy1, cy2));
            p = q;
            while (q < n && k[q] == k[p]) q++;
        }
        return (x_max - x_min) * (y_max - y_min);
    }
};

上一题