原题描述
完美矩形 在codetop被标记为腾讯考过的题目,也是leetcode原题。大概就是给一堆矩形,判断这些矩形是否能够形成一个大矩形,无重叠,原文的描述是精准覆盖。
思路解法
哈希表方法
思路说明
很容易想到的一点就是找出大矩形的上下左右四条边,确定一下大矩形的四个顶点,然后计算面积,和各个小矩形的面积之和比较。但是这种方法存在一些问题,比如下图,显然在这种方法下,下图的几个小矩形也能精确覆盖一个大矩形。

所以,还需要加以其他的判断标准,注意到,大矩形四个顶点在小矩形的各个顶点中只应该出现一次,而内部的那些点呢?应该是只能出现两次或者四次,如果只出现一次或者三次或者五次以以上的话,就是发生了重叠或者内部空缺。可以多看几个例子。



根据这两个标准就能够准确无误地进行判断了。
代码
func isRectangleCover(rectangles [][]int) bool {
// 遍历,找出大矩形的四个顶点,计算小矩形的面积之和,以及统计各个顶点出现的次数
mx := 100001
my := 100001
nx := -100001
ny := -100001
var totalArea int64
pointCounts := make(map[string]int, 0)
for _, rectangle := range rectangles {
mx = min(mx, rectangle[0])
nx = max(nx, rectangle[2])
my = min(my, rectangle[1])
ny = max(ny, rectangle[3])
totalArea += int64(rectangle[2] - rectangle[0]) * int64(rectangle[3] - rectangle[1])
pointCounts[fmt.Sprintf("%d*%d", rectangle[0], rectangle[1])]++
pointCounts[fmt.Sprintf("%d*%d", rectangle[0], rectangle[3])]++
pointCounts[fmt.Sprintf("%d*%d", rectangle[2], rectangle[1])]++
pointCounts[fmt.Sprintf("%d*%d", rectangle[2], rectangle[3])]++
}
// 先判断面积是否相等
flag := totalArea == int64(nx - mx) * int64(ny - my)
if !flag {
return flag
}
// 遍历pointCounts, 每一个点出现的次数
for point, count := range pointCounts {
if !isBigRecPoint(point, mx, my, nx, ny) { // 不是四角顶点
flag = flag && (count == 2 || count == 4) // 内部点出现两次或者一次
} else {
flag = flag && (count == 1) // 四角顶点只出现一次
}
if !flag {
return flag
}
}
return flag
}
func isBigRecPoint(point string, mx, my, nx, ny int) bool {
xys := strings.Split(point, "*")
if len(xys) != 2 {
return false
}
return (strconv.Itoa(mx) == xys[0] || strconv.Itoa(nx) == xys[0]) && (
strconv.Itoa(my) == xys[1] || strconv.Itoa(ny) == xys[1])
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
4865

被折叠的 条评论
为什么被折叠?



