Union-Find, 并查集应用

  • 开始做题之前,要注意先把定义和可能的各种 test case 正确输出弄清楚。在 LeetCode 上就只能反复提交试错,但是面试的时候,做题之前这些都是要通过交流去问清楚的,要么后面会浪费很多时间去涂涂改改,甚至发现一开始就答错了。。

给定一个 Set of Nodes ,Tree 要满足两个条件:

  • 无环

  • 单 root 节点

把这两点搞清楚之后,这题就很简单了。先一个一个 edge 去加,如果发现有环的话直接返回 false;否则跑到最后,看看最终的 number of connected components 是不是 1.

第一次写的时候用了个 HashSet 记录哪些点访问过,显得麻烦,还浪费了额外空间。

  • 这种在矩阵上做 flood filling 的问题,可以靠自定义字符做标记,取代用额外空间的记录方式。

这段代码的逻辑就是从四个边开始碰到 'O' 就往里扫,把扫到的都标上 'S' 代表有效湖;最后过一遍的时候除了 'S' 的都标成 'X' 就好了。

然而在大矩阵上 stackoverflow... 看来无脑 dfs 的做法还不够经济啊。。。

写了个 BFS 的在一个中型矩阵上 TLE了,我有点方。。

同样的 DFS 逻辑,做了如下改动之后就不会 stackoverflow 了:

  • DFS 时不进入最外围一圈的位置

简单来讲是在尽可能限制 DFS call stack 的层数,控制 DFS 的深度。从正确性上讲,上面的写法也是正确的,但是在极端情况下如果某一个从边沿出发的 DFS 连通了另一个边沿出发的 DFS,会导致一次的搜索路径非常长,于是 stackoverflow. 既然边沿的格子无论如何都要检查一遍,就把外圈封住,减少每个起点的 search tree depth.

这题当然也可以用 Union-Find 写,先把所有最外圈的 boundry 连上,然后把里面的相邻 'O' 做 union,最后扫矩阵的时候,如果对应的 root 不是 boundry root 就留下,不然都改成 'X'.

不过只是在这个问题上,不是很简洁。

Last updated

Was this helpful?