算法编程题-完美矩形

原题描述

完美矩形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)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值