【刷题笔记】更骚的并查集

更骚的并查集

写在前面

打个小广告:

最近在学Golang,开了用Go语言实现算法的仓库,有兴趣的同学们可以来贡献哦~

网址在这⬇️

Project alGo

如果你每天有力扣每日一题的习惯,你可能会感叹:

1月可真是一个图论月

确实如此,

而并查集是解决连通分量问题以及具有传递关系问题的特色解法

并查集

并查集本身有两个优化方案:

  • 路径压缩
    • Find() 方法中,将子树的节点拉到根节点,如此提高查找效率
  • 按秩合并
    • 维护每个节点子树的高度或节点数量,在合并时考察这个值。

我们要清楚并查集的作用是:

将两个联通分量合并成一个联通分量

803. 打砖块

问题描述
有一个 m x n 的二元网格,其中 1 表示砖块,0 表示空白。砖块 稳定(不会掉落)的前提是:

一块砖直接连接到网格的顶部,或者
至少有一块相邻(4 个方向之一)砖块 稳定 不会掉落时
给你一个数组 hits ,这是需要依次消除砖块的位置。每当消除 hits[i] = (rowi, coli) 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而掉落。一旦砖块掉落,它会立即从网格中消失(即,它不会落在其他稳定的砖块上)。

返回一个数组 result ,其中 result[i] 表示第 i 次消除操作对应掉落的砖块数目。

注意,消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。
示例 1:

输入:grid = [[1,0,0,0],[1,1,1,0]], hits = [[1,0]]
输出:[2]
解释:
网格开始为:
[[1,0,0,0],
 [1,1,1,0]]
消除 (1,0) 处加粗的砖块,得到网格:
[[1,0,0,0]
 [0,1,1,0]]
两个加粗的砖不再稳定,因为它们不再与顶部相连,也不再与另一个稳定的砖相邻,因此它们将掉落。得到网格:
[[1,0,0,0],
 [0,0,0,0]]
因此,结果为 [2] 
示例 2:

输入:grid = [[1,0,0,0],[1,1,0,0]], hits = [[1,1],[1,0]]
输出:[0,0]
解释:
网格开始为:
[[1,0,0,0],
 [1,1,0,0]]
消除 (1,1) 处加粗的砖块,得到网格:
[[1,0,0,0],
 [1,0,0,0]]
剩下的砖都很稳定,所以不会掉落。网格保持不变:
[[1,0,0,0], 
 [1,0,0,0]]
接下来消除 (1,0) 处加粗的砖块,得到网格:
[[1,0,0,0],
 [0,0,0,0]]
剩下的砖块仍然是稳定的,所以不会有砖块掉落。
因此,结果为 [0,0] 。

思路

我们知道,并查集的思想,

是将两个分立的节点集合组成一个连通分量

我们观察这道题的题意:

每当消除 hits[i] = (rowi, coli) 位置上的砖块时,
对应位置的砖块(若存在)会消失,
然后其他的砖块可能因为这一消除操作而掉落。

我来翻译一下这句话:

当一个连通分量的根节点被打掉之后,

该连通分量的其他节点会相应被消失

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Sp1lqnM-1610784124423)(/Users/alex/Library/Application Support/typora-user-images/截屏2021-01-16 下午2.37.30.png)]

想了20分钟,这似乎并不能用并查集来解决

因为并查集解决的是将两个集合分量Union(连通)在一起

而这里的过程是将两个分量拆开

当然不能,但是如果倒着来一遍呢?就像TENET 的剧情那样

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1lX7Osx-1610784124427)(/Users/alex/Library/Application Support/typora-user-images/截屏2021-01-16 下午2.42.39.png)]

这一切都顺理成章了,两个分开的元素被原来打掉的元素合并在了一起。

这便是这道题的关键思想。

编码

  1. 首先,既然用到了并查集,我们应该把并查集的代码模版先写出来,读者可以试着自己默写一遍,回过头来看这段代码:
	// 并查集的底层 size稍后解释
	parent := make([]int,size+1)
	// 并查集每个元素的秩,即根节点对应的集合大小
	ufsize := make([]int,size+1)

	// initiating
	// -----------------------------------
	for i := 0;i<=size;i++ {
   
		parent[i] = i
		ufsize[i] = 1
	}

	var Find = func
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值