题目:
给定在 xy 平面上的一组点,确定由这些点组成的矩形的最小面积,其中矩形的边平行于 x 轴和 y 轴。
如果没有任何矩形,就返回 0。
算法:
方法一:模拟
这个方法只考虑了一条对角线,我们需要考虑两条对角线,四个点都存在。
func minAreaRect(points [][]int) int {
if len(points) < 2 {
return 0
}
ans := math.MaxInt32
n := len(points)
for i := 0; i < n - 1; i ++ {
for j := i + 1; j < n; j ++ {
area := getArea(points[i], points[j])
if area != 0 && area < ans {
fmt.Println(area, points[i], points[j])
ans = area
}
}
}
return ans
}
func getArea(point1, point2 []int) int {
return abs((point1[0] - point2[0]) * (point1[1] - point2[1]))
}
func abs(x int) int {
if x < 0 {
return -1 * x
}
return x
}
方法二:模拟
在方法一的基础上,用hash表存储另一条对角线的两个点是否存在。因为一个点(x,y)的取值范围为[0,4000],我们用x * 4001 + y 作为key,用hash map保存一个点是否存在,这也是一个常用的技巧,记忆某个位置是否存在,将多维的数据转化为一维,生成hash map的key。
为什么不用x * 4000 + y生成key呢, (0,4000)和(1,0)的key都是4000,我们用x * 4001和y可以保证这两个数没有交集,key不会重复。
这个题目要理解矩形的四个点都要存在
func minAreaRect(points [][]int) int {
if len(points) < 2 {
return 0
}
ans := math.MaxInt32
n := len(points)
exist := make(map[int]struct{})
for i := range points {
exist[getKey(points[i][0],points[i][1])] = struct{}{}
}
for i := 0; i < n - 1; i ++ {
for j := i + 1; j < n; j ++ {
area := getArea(points[i],points[j])
_, ok1 := exist[getKey(points[i][0],points[j][1])]
_, ok2 := exist[getKey(points[j][0],points[i][1])]
if ok1 && ok2 && area != 0 && area < ans {
fmt.Println(points[i],points[j])
ans = area
}
}
}
if ans == math.MaxInt32 {
return 0
}
return ans
}
func getKey(x, y int) int {
return x * 40001 + y
}
func getArea(point1, point2 []int) int {
return abs((point1[0] - point2[0]) * (point1[1] - point2[1]))
}
func abs(x int) int {
if x < 0 {
return -1 * x
}
return x
}