You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
定义两个字符串变量:s和m,再定义两种操作,
第一种操作:
m = s;
s = s + s;
第二种操作:
s = s + m;
假设s, m初始化如下:
s = "a";
m = s;
求最小的操作步骤数,可以将s拼接到长度等于n
输入一个整数n,表明我们需要得到s字符长度,0<n<10000
案例:
in:
6
out:
3
0. 前言
广度优先搜索(BFS)和深度优先搜索(DFS),大家可能在oj上见过,各种求路径、最短路径、最优方法、组合等等。于是,我们不妨动手试一下js版本怎么玩。
1.队列、栈
队列是先进先出,后进后出,常用的操作是取第一个元素(shift)、尾部加入一个元素(push)。
栈是后进先出,就像一个垃圾桶,后入的垃圾先被倒出来。常用的操作是,尾部加入元素(push),尾部取出元素(pop)
2.BFS
BFS是靠一个队列来辅助运行的。顾名思义,广度搜索,就是对于一个树形结构,我们一层层节点去寻找目标节点。
按照这个顺序进行广度优先遍历,明显是队列可以完美配合整个过程:
到了最后,队列清空,树也遍历了一次
1.1 矩阵形式的图的遍历
假设有几个点,我们需要设计一个算法,判定两个点有没有相通
假设点12345是这样的结构:
问:1能不能到达5
显然我们一眼看上去是不会到达的,如果是设计算法的话,怎么做呢?
我们把点之间的关系用一个矩阵表示,0表示不连接,n行m列的1表示点n通向点m
1.2 树的BFS举例
举个例子,3月24号今日头条笔试题第二题的最少操作步数:
思路:利用广度优先搜索,假设左节点是操作1,右节点是操作2,这样子就形成了操作树。利用bfs的规则,把上层的父节点按顺序加入队列,然后从前面按顺序移除,同时在队列尾部加上移除的父节点的子节点。我这里,先把父节点拿出来对比,他的子节点放在temp,对比完了再把子节点追加上去
每个节点分别用两个数记录s,m。发现第一次两种操作是一样的,所以我就略去右边的了
3.DFS
DFS着重于这个搜索的过程,一般以“染色”的形式配合栈来运行,也比较彻底。V8老生代的垃圾回收机制中的标记-清除也利用了DFS。我们定义三种颜色:黑白灰,白色是未处理过的,灰是已经经过了但没有处理,黑色是已经处理过了
还是前面那幅图
我们用两个数组,一个是栈,一个是保存我们遍历顺序的,数组的元素拿到的都是原对象树的引用,是会改变原对象的节点颜色的
我们可以看到,入栈的时候,从白色染灰色,出栈的时候,从灰色到黑色。整个过程中,染黑的顺序类似于二叉树的后序遍历
v8的垃圾回收,将持有引用的变量留下,没有引用的变量清除。因为如果持有引用,他们必然在全局的树中被遍历到。如果没有引用,那这个变量必然永远是白色,就会被清理
我们用对象来表示上面这棵树:
开始我们的DFS:
过程用递归比较简单,上面大部分代码都是调试代码,自己可以改一下测试其他的类似场景。遍历完成后,tree上面每一个节点都是黑色了。遍历中间过程,每一个节点入栈的时候是灰色的,出栈的时候是黑色的。
The text was updated successfully, but these errors were encountered: