商城网站建设天软科技,宁夏建设职业技术学院网站,个人做房产网站,企业手机网站 案例最大三角形面积
问题描述
给定包含 n 个点的数组 points#xff0c;其中 points[i] [xi, yi] 表示平面上的一个点。
返回由其中任意三个点组成的三角形的最大面积。
示例#xff1a;
输入: points [[0,0],[0,1],[1,0],[0,2],[2,0]]
输出: 2.00000
解释: 选择点 [0,2], [2,0…最大三角形面积问题描述给定包含n个点的数组points其中points[i] [xi, yi]表示平面上的一个点。返回由其中任意三个点组成的三角形的最大面积。示例输入: points [[0,0],[0,1],[1,0],[0,2],[2,0]] 输出: 2.00000 解释: 选择点 [0,2], [2,0], [0,0] 组成的三角形面积最大为 2。算法思路核心三角形面积公式给定三个点 A(x₁,y₁), B(x₂,y₂), C(x₃,y₃)三角形面积为Area 0.5 × |x₁(y₂ - y₃) x₂(y₃ - y₁) x₃(y₁ - y₂)|这是叉积公式的简化形式。暴力枚举3 points.length 50三重循环的时间复杂度O(n³) 50³ 125,000可以接受优化可以使用凸包算法Andrew算法先求凸包然后在凸包上找最大三角形对于 n ≤ 50 的小数据暴力更简单方法暴力三重循环枚举所有可能的三点组合计算面积并记录最大值凸包对于大数据集更优代码实现方法一暴力枚举classSolution{/** * 使用暴力枚举找到最大三角形面积 * * param points 点的坐标数组points[i] [x, y] * return 最大三角形面积 */publicdoublelargestTriangleArea(int[][]points){intnpoints.length;doublemaxArea0.0;// 三重循环枚举所有三点组合for(inti0;in;i){for(intji1;jn;j){for(intkj1;kn;k){// 计算三角形面积doubleareacalculateTriangleArea(points[i][0],points[i][1],points[j][0],points[j][1],points[k][0],points[k][1]);maxAreaMath.max(maxArea,area);}}}returnmaxArea;}/** * 使用叉积公式计算三角形面积 * * param x1, y1 第一个点的坐标 * param x2, y2 第二个点的坐标 * param x3, y3 第三个点的坐标 * return 三角形面积 */privatedoublecalculateTriangleArea(intx1,inty1,intx2,inty2,intx3,inty3){// 叉积公式Area 0.5 * |x1(y2 - y3) x2(y3 - y1) x3(y1 - y2)|doublearea0.5*Math.abs(x1*(y2-y3)x2*(y3-y1)x3*(y1-y2));returnarea;}}方法二向量叉积classSolution{/** * 使用向量叉积计算面积 * 将三角形看作两个向量的叉积 */publicdoublelargestTriangleArea(int[][]points){intnpoints.length;doublemaxArea0.0;for(inti0;in;i){for(intji1;jn;j){for(intkj1;kn;k){// 以points[i]为原点构造两个向量int[]vector1{points[j][0]-points[i][0],points[j][1]-points[i][1]};int[]vector2{points[k][0]-points[i][0],points[k][1]-points[i][1]};// 叉积的绝对值的一半就是面积doublearea0.5*Math.abs(vector1[0]*vector2[1]-vector1[1]*vector2[0]);maxAreaMath.max(maxArea,area);}}}returnmaxArea;}}方法三凸包importjava.util.*;classSolution{/** * 使用凸包最大面积三角形的三个顶点一定在凸包上 */publicdoublelargestTriangleArea(int[][]points){// 先计算凸包int[][]convexHullcomputeConvexHull(points);intnconvexHull.length;// 如果凸包点数小于3无法构成三角形if(n3){return0.0;}doublemaxArea0.0;// 在凸包上暴力枚举for(inti0;in;i){for(intji1;jn;j){for(intkj1;kn;k){doubleareacalculateTriangleArea(convexHull[i][0],convexHull[i][1],convexHull[j][0],convexHull[j][1],convexHull[k][0],convexHull[k][1]);maxAreaMath.max(maxArea,area);}}}returnmaxArea;}/** * 使用Andrew算法计算凸包 */privateint[][]computeConvexHull(int[][]points){intnpoints.length;if(n1)returnpoints;// 按x坐标排序x相同时按y排序Arrays.sort(points,(a,b)-{if(a[0]!b[0])returna[0]-b[0];returna[1]-b[1];});Listint[]hullnewArrayList();// 构建下凸包for(inti0;in;i){while(hull.size()2cross(hull.get(hull.size()-2),hull.get(hull.size()-1),points[i])0){hull.remove(hull.size()-1);}hull.add(points[i]);}// 构建上凸包intlowerSizehull.size();for(intin-2;i0;i--){while(hull.size()lowerSizecross(hull.get(hull.size()-2),hull.get(hull.size()-1),points[i])0){hull.remove(hull.size()-1);}hull.add(points[i]);}// 移除重复的起点如果凸包点数1if(hull.size()1){hull.remove(hull.size()-1);}returnhull.toArray(newint[0][]);}/** * 计算叉积(p2 - p1) × (p3 - p1) */privatelongcross(int[]p1,int[]p2,int[]p3){return(long)(p2[0]-p1[0])*(p3[1]-p1[1])-(long)(p2[1]-p1[1])*(p3[0]-p1[0]);}privatedoublecalculateTriangleArea(intx1,inty1,intx2,inty2,intx3,inty3){return0.5*Math.abs(x1*(y2-y3)x2*(y3-y1)x3*(y1-y2));}}算法分析时间复杂度暴力O(n³)n ≤ 50凸包O(n log n h³)h是凸包点数空间复杂度暴力O(1)凸包O(n) - 存储凸包点算法过程1points [[0,0],[0,1],[1,0],[0,2],[2,0]]三点组合[0,0], [0,2], [2,0]面积 0.5 × |0×(2-0) 0×(0-0) 2×(0-2)| 0.5 × |0 0 2×(-2)| 0.5 × 4 2.0[0,0], [0,1], [1,0]面积 0.5 × |0×(1-0) 0×(0-0) 1×(0-1)| 0.5 × 1 0.5[0,1], [0,2], [2,0]面积 0.5 × |0×(2-0) 0×(0-1) 2×(1-2)| 0.5 × 2 1.0最大面积2.0测试用例publicstaticvoidmain(String[]args){SolutionsolutionnewSolution();// 测试用例1标准示例int[][]points1{{0,0},{0,1},{1,0},{0,2},{2,0}};System.out.printf(Test 1: %.5f\n,solution.largestTriangleArea(points1));// 2.00000// 测试用例2等边三角形int[][]points2{{0,0},{1,0},{0,1}};System.out.printf(Test 2: %.5f\n,solution.largestTriangleArea(points2));// 0.50000// 测试用例3三点共线面积为0int[][]points3{{0,0},{1,1},{2,2}};System.out.printf(Test 3: %.5f\n,solution.largestTriangleArea(points3));// 0.00000// 测试用例4正方形的四个顶点int[][]points4{{0,0},{0,1},{1,1},{1,0}};System.out.printf(Test 4: %.5f\n,solution.largestTriangleArea(points4));// 0.50000// 测试用例5最小情况正好3个点int[][]points5{{0,0},{3,0},{0,4}};System.out.printf(Test 5: %.5f\n,solution.largestTriangleArea(points5));// 6.00000// 测试用例6包含负坐标int[][]points6{{-1,-1},{1,1},{0,2}};System.out.printf(Test 6: %.5f\n,solution.largestTriangleArea(points6));// 2.00000// 测试用例7大坐标值int[][]points7{{0,0},{100,0},{0,100}};System.out.printf(Test 7: %.5f\n,solution.largestTriangleArea(points7));// 5000.00000// 测试用例8多个点但最大三角形由特定三点构成int[][]points8{{0,0},{1,1},{2,2},{3,0},{0,3}};System.out.printf(Test 8: %.5f\n,solution.largestTriangleArea(points8));// 4.50000// 测试用例9所有点都在一个圆上正多边形int[][]points9{{1,0},{0,1},{-1,0},{0,-1}};System.out.printf(Test 9: %.5f\n,solution.largestTriangleArea(points9));// 1.00000// 测试用例10边界情况 - 重复点int[][]points10{{0,0},{0,0},{1,0},{0,1}};System.out.printf(Test 10: %.5f\n,solution.largestTriangleArea(points10));// 0.50000}关键点面积公式叉积公式最稳定避免了浮点运算误差不需要计算边长或角度直接使用坐标绝对值叉积可能为负取决于点的顺序取绝对值确保面积为正三点共线叉积为0时三点共线面积为0常见问题为什么最大三角形的顶点一定在凸包上这是一个几何定理给定平面上的点集面积最大的三角形的三个顶点必定在点集的凸包上因为如果有一个顶点在凸包内部可以向外移动到凸包边界面积会增大叉积公式基于向量叉积的几何意义|a × b| |a||b|sinθ三角形面积 0.5 × |a||b|sinθ 0.5 × |a × b|