Depth-first Search深度优先搜索专题7

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flying_all/article/details/82287168

834 Sum of Distances in Tree

思路:一颗无向的树有N个节点,分别标记为0,1,2,…N-1,有若干条边。结果返回每个节点到其他节点的路径和。
这里写图片描述
以上面这棵树为例。从节点0到其他点的路径查找过程是:节点0有两条边分别到达子节点1和子节点2;递归查找节点1(节点1没有子节点),节点2;继续查找节点2的子节点…依次下去。递归每进一层,路径就需要加1。
遍历完节点0以后,再以节点1为根节点,遍历。
时间复杂度O(N*E),E是边的数目。这个思路超时。既然是超时,定是因为有重复计算的。例如遍历边(0,2),之后又遍历了一次(2,0)。但是该怎么合并计算,我没想出来。
学习:接下来的描述,相当于翻译官方解释吧。
这里写图片描述
用一颗新的树为例子。节点0和节点4是父子关系,也是相邻节点。现在观察一下相邻节点连接后,路径和发生什么变化。
将节点0和节点4的路径断开,得到下图。
节点0的子树 节点4的子树
记:stsum[0] 表示节点0在节点0子树上的路径和。stsum[4]表示节点4在节点4子树上的路径和。count[0]表示节点0子树的节点数。answer[0]表示节点0在整个树的路径和。answer[4]表示节点4在整个树的路径和。

当节点0和节点4之间加上路径后,answer[0]= stsum[0] + stsum[4] + count[4]。因为节点0到节点4子树上所有点的距离与节点4到节点4子树上所有点的距离都要加1。answer[4]= stsum[4] + stsum[0] + count[0]。而且能得到answer[0]-answer[4]=count[4]-count[0]。

所以得到结论:相邻节点(父子节点)x,y在整个树的路径和是: a n s w e r [ x ] a n s w e r [ y ] = c o u n t [ y ] c o u n t [ x ] answer[x] -answer[y] = count[y] - count[x]
编码过程:
1 answer[]存储以每个节点为根节点在整个树的路径和;
2 count[] 存储以每个节点为根节点的子树的节点数,初始化每个元素值=1;
3 对某个节点node,dfs后序遍历,先处理子节点,计算每个子节点y的count和stsum, c o u n t [ n o d e ] + = c o u n t [ c h i l d ] count[node]+=count[child] s t s u m [ n o d e ] + = s t s u m [ c h i l d ] + c o u n t [ c h i l d ] stsum[node] +=stsum[child]+count[child] ,当遍历了所有的边以后 a n s w e r [ n o d e ] = s t s u m [ n o d e ] answer[node] = stsum[node] ;如果我们从节点0开始遍历。这次遍历结束后只有answer[0]是正确的。其他节点都没有遍历完全。
4 再看,上面分析了两个相邻节点(父子节点)的路径和关系。如果有节点parent和子节点child,则有 a n s w e r [ c h i l d ] = a n s w e r [ p a r e n t ] c o u n t [ c h i l d ] + ( N c o u n t [ c h i l d ] ) answer[child] = answer[parent] - count[child] + (N - count[child]) ,因为我们已经得到answer[0]的正确结果,可以依据算式计算节点0的子节点的answer。算式中之所以使用count[child]来计算count[parent]: N c o u n t [ c h i l d ] ) = c o u n t [ p r e n t ] N - count[child])=count[prent] ,是因为在上一步的后续遍历过程中,count[parent]的值已经发生变化,不再是parent、child状态下的count
(原文的解释是:count[child]从child得到parent比较容易)。用先序遍历再次遍历树,修改每个子节点的answer,得到最终结果。
代码

301 Remove Invalid Parentheses

思路:最直接的想法:把s中每一个(,)去掉,检查新的字符串是不是有效字符串,如果是则加入到结果集。
这样不符合题意的要求:去掉最少的括号。那么需要计算最少去掉几个左括号,去掉几个右括号,就可以是有效字符串。
在编码过程中注意去重。
代码
学习:可以改进,不再需要判断是否是有效字符串。添加变量open。有效字符的特征是:左括号在前,所以open>0;左右括号个数相同=>open=0;多余的左右括号都去掉了=>leftCount=0 and rightCount=0。
代码

猜你喜欢

转载自blog.csdn.net/flying_all/article/details/82287168