leetcode
leetcode 701 ~ 750
最大三角形面积

最大三角形面积

难度:

标签:

题目描述

给你一个由 X-Y 平面上的点组成的数组 points ,其中 points[i] = [xi, yi] 。从其中取任意三个不同的点组成三角形,返回能组成的最大三角形的面积。与真实值误差在 10-5 内的答案将会视为正确答案

 

示例 1:

输入:points = [[0,0],[0,1],[1,0],[0,2],[2,0]]
输出:2.00000
解释:输入中的 5 个点如上图所示,红色的三角形面积最大。

示例 2:

输入:points = [[1,0],[0,0],[0,1]]
输出:0.50000

 

提示:

  • 3 <= points.length <= 50
  • -50 <= xi, yi <= 50
  • 给出的所有点 互不相同

代码结果

运行时间: 42 ms, 内存: 16.1 MB


/*
 * 思路:
 * 1. 使用 Java Stream API 进行遍历和计算。
 * 2. 计算所有三点组合的三角形面积并返回最大值。
 */

import java.util.Arrays;
import java.util.Comparator;

public class Solution {
    public double largestTriangleArea(int[][] points) {
        return Arrays.stream(points)
                .flatMapToDouble(p1 -> Arrays.stream(points)
                        .flatMapToDouble(p2 -> Arrays.stream(points)
                                .mapToDouble(p3 -> Math.abs(
                                        p1[0] * (p2[1] - p3[1]) +
                                        p2[0] * (p3[1] - p1[1]) +
                                        p3[0] * (p1[1] - p2[1])
                                ) / 2.0)
                                .filter(area -> area > 0)))
                .max()
                .orElse(0);
    }
}

解释

方法:

该题解采用的是计算凸包和在凸包上查找最大三角形面积的方法。首先,使用Graham扫描算法计算点集的凸包,这保证了三角形的顶点位于凸包的顶点上,这是因为非凸包点无法形成最大面积的三角形。计算凸包后,对凸包上的每对点(作为三角形的两个顶点),使用旋转卡壳技术优化地寻找第三个点,这个点使得三角形的面积最大。通过对每个固定的边,逐步旋转至最佳的第三点位置,可有效地找到最大面积。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
在Graham扫描算法中,如何确定使用向量叉积来计算凸包的正确性,特别是在处理边界点的时候?
Graham扫描算法使用向量叉积来确定三个点的相对位置,进而决定是否将点包括在凸包内。向量叉积结果为正,表示三个点构成的转向是逆时针;为负则为顺时针;为零则三点共线。在构建凸包时,我们希望保留构成凸包边界的逆时针转向,因此,当叉积为非正时(即顺时针或共线),当前点不应加入凸包。这种方法确保了在处理边界点时,只有当新点能与已有的凸包边界维持逆时针关系时才被添加,从而正确地构造出凸包的下半部和上半部。
🦆
旋转卡壳技术在寻找最大三角形面积时的效率为什么比传统方法高,能否详细说明其优化的核心原理?
旋转卡壳技术优化了在凸包上寻找最大三角形面积的过程。传统方法需要对凸包上的每个点对进行三重循环查找最大面积,时间复杂度为O(n^3)。旋转卡壳技术通过固定两点,然后通过旋转找到使三角形面积最大的第三点,这一点通常是对腰的对角线方向上的点。核心原理是在固定一条边的情况下,第三点位置的最优解是单调的,即随着边的旋转,第三点也按一定方向移动,不需要每次都重头搜索,从而将搜索时间从线性减少到常数时间,整体算法复杂度降为O(n^2)。
🦆
对于凸包中的每一对点,如何保证使用旋转卡壳技术找到的第三点确实是使得面积最大的点?
在旋转卡壳技术中,对于凸包上的每对固定点(A和B),算法通过逐步旋转来选择作为第三点的C。由于凸包上的点是按顺序排列的,当从点A和点B出发,逐步增加第三点C的索引时,三角形ABC的面积会首先增加直到达到最大值,然后开始减小。这是因为凸包的性质保证了点的线性序,避免了内部的“突出”点干扰。一旦面积开始减少,就不再需要继续搜索,因为后续的三角形面积将会继续减小。这种方法确保了找到的第三点是能够使三角形面积最大化的点。

相关问题

三角形的最大周长

给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0

 

示例 1:

输入:nums = [2,1,2]
输出:5
解释:你可以用三个边长组成一个三角形:1 2 2。

示例 2:

输入:nums = [1,2,1,10]
输出:0
解释:
你不能用边长 1,1,2 来组成三角形。
不能用边长 1,1,10 来构成三角形。
不能用边长 1、2 和 10 来构成三角形。
因为我们不能用任何三条边长来构成一个非零面积的三角形,所以我们返回 0。

 

提示:

  • 3 <= nums.length <= 104
  • 1 <= nums[i] <= 106