跳转至

3588. 找到最大三角形面积

题目描述

给你一个二维数组 coords,大小为 n x 2,表示一个无限笛卡尔平面上 n 个点的坐标。

找出一个 最大 三角形的 两倍 面积,其中三角形的三个顶点来自 coords 中的任意三个点,并且该三角形至少有一条边与 x 轴或 y 轴平行。严格地说,如果该三角形的最大面积为 A,则返回 2 * A

如果不存在这样的三角形,返回 -1。

注意,三角形的面积 不能 为零。

 

示例 1:

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

输出: 2

解释:

图中的三角形的底边为 1,高为 2。因此,它的面积为 1/2 * 底边 * 高 = 1

示例 2:

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

输出: -1

解释:

唯一可能的三角形的顶点是 (1, 1)(2, 2)(3, 3)。它的任意边都不与 x 轴或 y 轴平行。

 

提示:

  • 1 <= n == coords.length <= 105
  • 1 <= coords[i][0], coords[i][1] <= 106
  • 所有 coords[i] 都是 唯一 的。

解法

方法一:枚举 + 哈希表

题目要求三角形的两倍面积,因此我们可以直接计算三角形的底边和高的乘积。

又因为三角形至少有一条边与 \(x\) 轴或 \(y\) 轴平行,我们可以枚举与 \(x\) 轴平行的边,计算所有可能的三角形的两倍面积,然后将 \(\textit{coords}\) 横纵坐标交换后,重复上述过程,计算与 \(y\) 轴平行的边的所有可能的三角形的两倍面积。

因此,我们设计一个函数 \(\textit{calc}\) 来计算与 \(y\)轴平行的边的所有可能的三角形的两倍面积。

我们用两个哈希表 \(\textit{f}\)\(\textit{g}\) 来记录每个横坐标对应的最小纵坐标和最大纵坐标。然后我们遍历 \(\textit{coords}\),更新哈希表 \(\textit{f}\)\(\textit{g}\),同时记录横坐标的最小值和最大值。最后,我们遍历哈希表 \(\textit{f}\),计算每个横坐标对应的三角形的两倍面积,并更新答案。

在主函数中,我们先调用 \(\textit{calc}\) 函数计算与 \(y\) 轴平行的边的所有可能的三角形的两倍面积,然后将 \(\textit{coords}\) 横纵坐标交换后,重复上述过程,计算与 \(x\) 轴平行的边的所有可能的三角形的两倍面积。最后返回答案,如果答案为 0,则返回 -1。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\)\(\textit{coords}\) 的长度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def maxArea(self, coords: List[List[int]]) -> int:
        def calc() -> int:
            mn, mx = inf, 0
            f = {}
            g = {}
            for x, y in coords:
                mn = min(mn, x)
                mx = max(mx, x)
                if x in f:
                    f[x] = min(f[x], y)
                    g[x] = max(g[x], y)
                else:
                    f[x] = g[x] = y
            ans = 0
            for x, y in f.items():
                d = g[x] - y
                ans = max(ans, d * max(mx - x, x - mn))
            return ans

        ans = calc()
        for c in coords:
            c[0], c[1] = c[1], c[0]
        ans = max(ans, calc())
        return ans if ans else -1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
    public long maxArea(int[][] coords) {
        long ans = calc(coords);
        for (int[] c : coords) {
            int tmp = c[0];
            c[0] = c[1];
            c[1] = tmp;
        }
        ans = Math.max(ans, calc(coords));
        return ans > 0 ? ans : -1;
    }

    private long calc(int[][] coords) {
        int mn = Integer.MAX_VALUE, mx = 0;
        Map<Integer, Integer> f = new HashMap<>();
        Map<Integer, Integer> g = new HashMap<>();

        for (int[] c : coords) {
            int x = c[0], y = c[1];
            mn = Math.min(mn, x);
            mx = Math.max(mx, x);
            if (f.containsKey(x)) {
                f.put(x, Math.min(f.get(x), y));
                g.put(x, Math.max(g.get(x), y));
            } else {
                f.put(x, y);
                g.put(x, y);
            }
        }

        long ans = 0;
        for (var e : f.entrySet()) {
            int x = e.getKey();
            int y = e.getValue();
            int d = g.get(x) - y;
            ans = Math.max(ans, (long) d * Math.max(mx - x, x - mn));
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
    long long maxArea(vector<vector<int>>& coords) {
        auto calc = [&]() -> long long {
            int mn = INT_MAX, mx = 0;
            unordered_map<int, int> f, g;
            for (auto& c : coords) {
                int x = c[0], y = c[1];
                mn = min(mn, x);
                mx = max(mx, x);
                if (f.count(x)) {
                    f[x] = min(f[x], y);
                    g[x] = max(g[x], y);
                } else {
                    f[x] = y;
                    g[x] = y;
                }
            }
            long long ans = 0;
            for (auto& [x, y] : f) {
                int d = g[x] - y;
                ans = max(ans, 1LL * d * max(mx - x, x - mn));
            }
            return ans;
        };

        long long ans = calc();
        for (auto& c : coords) {
            swap(c[0], c[1]);
        }
        ans = max(ans, calc());
        return ans > 0 ? ans : -1;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func maxArea(coords [][]int) int64 {
    calc := func() int64 {
        mn, mx := int(1e9), 0
        f := make(map[int]int)
        g := make(map[int]int)
        for _, c := range coords {
            x, y := c[0], c[1]
            mn = min(mn, x)
            mx = max(mx, x)
            if _, ok := f[x]; ok {
                f[x] = min(f[x], y)
                g[x] = max(g[x], y)
            } else {
                f[x] = y
                g[x] = y
            }
        }
        var ans int64
        for x, y := range f {
            d := g[x] - y
            ans = max(ans, int64(d)*int64(max(mx-x, x-mn)))
        }
        return ans
    }

    ans := calc()
    for _, c := range coords {
        c[0], c[1] = c[1], c[0]
    }
    ans = max(ans, calc())
    if ans > 0 {
        return ans
    }
    return -1
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function maxArea(coords: number[][]): number {
    function calc(): number {
        let [mn, mx] = [Infinity, 0];
        const f = new Map<number, number>();
        const g = new Map<number, number>();

        for (const [x, y] of coords) {
            mn = Math.min(mn, x);
            mx = Math.max(mx, x);
            if (f.has(x)) {
                f.set(x, Math.min(f.get(x)!, y));
                g.set(x, Math.max(g.get(x)!, y));
            } else {
                f.set(x, y);
                g.set(x, y);
            }
        }

        let ans = 0;
        for (const [x, y] of f) {
            const d = g.get(x)! - y;
            ans = Math.max(ans, d * Math.max(mx - x, x - mn));
        }
        return ans;
    }

    let ans = calc();
    for (const c of coords) {
        [c[0], c[1]] = [c[1], c[0]];
    }
    ans = Math.max(ans, calc());
    return ans > 0 ? ans : -1;
}

评论