每日算法----812. 最大三角形面积----2022/05/15

32 篇文章 0 订阅
27 篇文章 0 订阅

1. 题目描述

给定包含多个点的集合,从其中取三个点组成三角形,返回能组成的最大三角形的面积。

2. 示例

给定包含多个点的集合,从其中取三个点组成三角形,返回能组成的最大三角形的面积。

示例:
输入: points = [[0,0],[0,1],[1,0],[0,2],[2,0]]
输出: 2
解释:
这五个点如下图所示。组成的橙色三角形是最大的,面积为2。
在这里插入图片描述
注意:

  • 3 <= points.length <= 50.
  • 不存在重复的点。
  • -50 <= points[i][j] <= 50.
  • 结果误差值在 10^-6 以内都认为是正确答案。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/largest-triangle-area
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

3. 思路

需要遍历节点,每次遍历获取三个点,计算三个点的面积。计算面积公式:0.5*底边长*高

  • 底边长:根据底边两端点进行计算获取,公式:sqrt((x1-x2)^2+(y1-y2)^2)
  • 高:底边对应点到底边的最短线段(垂线段),计算公式:abs((y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2)/sqrt((x1-x2) ^ 2+(y1-y2) ^ 2 )
  • 底边长*高的过程中可以约掉sqrt((x1-x2)^2+(y1-y2)^2)
  • 最终计算面积公式:0.5*abs((y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2)
4. 遇上的问题
  • 公式不熟悉,导致需要去查公式才能做题。
5. 具体实现代码

自己写的代码

func largestTriangleArea(points [][]int) float64{
	maxArea	:= 0.0
	for i := 0;i < len(points);i++{
		for j := i+1;j < len(points);j++{
			for k := j+1;k < len(points);k++{
				//已知两点,求两点间距离:sqrt[(X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2)]
				l1 :=  math.Sqrt(float64((points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1])*(points[i][1] - points[j][1])))
				l2 :=  math.Sqrt(float64((points[i][0] - points[k][0]) * (points[i][0] - points[k][0]) + (points[i][1] - points[k][1])*(points[i][1] - points[k][1])))
				l3 :=  math.Sqrt(float64((points[k][0] - points[j][0]) * (points[k][0] - points[j][0]) + (points[k][1] - points[j][1])*(points[k][1] - points[j][1])))
				//① 两条最短边之和>最长边。
				//② 最长边与最短边之差<第二长边。
				if l1+l2<=l3 || l3+l2<=l1  || l1+l3<=l2 || l1-l2>=l3 || l1-l3>=l2 || l2-l3>=l1{
					break
				}
				tempArea := 0.0
				//直线Ax+By+C=0 坐标(Xo,Yo)那么这点到这直线的距离就为:│AXo+BYo+C│/√(A2+B2)。
				//已知三点,求一点到另外两点连成线段的最短距离:d = abs((y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2)/sqrt((x1-x2) ^ 2+(y1-y2) ^ 2 )
				x1 := float64(points[i][0])
				x2 := float64(points[j][0])
				x3 := float64(points[k][0])
				y1 := float64(points[i][1])
				y2 := float64(points[j][1])
				y3 := float64(points[k][1])
				num := (y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2
				if num < 0{
					num*= -1
				}
				tempArea = 0.5* num
				if maxArea < tempArea{
					maxArea = tempArea
				}
			}
		}
	}
	return maxArea
}
6. 官方题解
func triangleArea(x1, y1, x2, y2, x3, y3 int) float64 {
    return math.Abs(float64(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)) / 2
}

func largestTriangleArea(points [][]int) (ans float64) {
    for i, p := range points {
        for j, q := range points[:i] {
            for _, r := range points[:j] {
                ans = math.Max(ans, triangleArea(p[0], p[1], q[0], q[1], r[0], r[1]))
            }
        }
    }
    return
}

这里调用了一个已知三角形三点求三角形面积的公式S=(x1y2-x1y3+x2y3-x2y1+x3y1-x2y2)。阿这,收获新公式。

这里的复杂度分析

时间复杂度:O(n^3),三重循环;空间复杂度:O(1)

官方还有一个解法凸包算法:时间复杂度:O(n^2),Andrew 算法的时间复杂度为 O(nlogn),在凸包上枚举三角形的时间复杂度为 O(n^2)。

空间复杂度:O(n)。Andrew 算法的空间复杂度为 O(n),保存凸包需要 O(n)的空间。

空间复杂度:O(n)

func cross(p, q, r []int) int {
    return (q[0]-p[0])*(r[1]-q[1]) - (q[1]-p[1])*(r[0]-q[0])
}

func getConvexHull(points [][]int) [][]int {
    n := len(points)
    if n < 4 {
        return points
    }

    // 按照 x 从小到大排序,如果 x 相同,则按照 y 从小到大排序
    sort.Slice(points, func(i, j int) bool { a, b := points[i], points[j]; return a[0] < b[0] || a[0] == b[0] && a[1] < b[1] })

    hull := [][]int{}
    // 求凸包的下半部分
    for _, p := range points {
        for len(hull) > 1 && cross(hull[len(hull)-2], hull[len(hull)-1], p) <= 0 {
            hull = hull[:len(hull)-1]
        }
        hull = append(hull, p)
    }
    // 求凸包的上半部分
    m := len(hull)
    for i := n - 1; i >= 0; i-- {
        for len(hull) > m && cross(hull[len(hull)-2], hull[len(hull)-1], points[i]) <= 0 {
            hull = hull[:len(hull)-1]
        }
        hull = append(hull, points[i])
    }
    // hull[0] 同时参与凸包的上半部分检测,因此需去掉重复的 hull[0]
    return hull[:len(hull)-1]
}

func triangleArea(x1, y1, x2, y2, x3, y3 int) float64 {
    return math.Abs(float64(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)) / 2
}

func largestTriangleArea(points [][]int) (ans float64) {
    convexHull := getConvexHull(points)
    n := len(convexHull)
    for i, p := range convexHull {
        for j, k := i+1, i+2; j+1 < n; j++ {
            q := convexHull[j]
            for ; k+1 < n; k++ {
                curArea := triangleArea(p[0], p[1], q[0], q[1], convexHull[k][0], convexHull[k][1])
                nextArea := triangleArea(p[0], p[1], q[0], q[1], convexHull[k+1][0], convexHull[k+1][1])
                if curArea >= nextArea {
                    break
                }
            }
            ans = math.Max(ans, triangleArea(p[0], p[1], q[0], q[1], convexHull[k][0], convexHull[k][1]))
        }
    }
    return
}

先列出来,没仔细看,留个坑给以后再补。

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/largest-triangle-area/solution/zui-da-san-jiao-xing-mian-ji-by-leetcode-yefh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

7 题目来源

leetCode


补充了点三角形计算公式。S=(x1y2-x1y3+x2y3-x2y1+x3y1-x2y2)------swrici

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值