939.最小面积矩形

168 阅读2分钟

题目:
给定在 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
}