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 题目来源
补充了点三角形计算公式。
S=(x1y2-x1y3+x2y3-x2y1+x3y1-x2y2)
------swrici