题目描述
今天是奇了怪了,连着两个面试都出了涉及到遍历和递归的算法题。先看下这道题的要求吧。
对于给定的对象数组结构,描述的是一颗树的节点关系,要求实现一个函数,找出这颗树所有的链路,以二维数组形式输出:
例如:
const list = [
{ id: 6 },
{ id: 2, children: [5] },
{ id: 13 },
{ id: 5, children: [10, 11] },
{ id: 1, children: [2, 3, 4] },
{ id: 10 },
{ id: 8, children: [13] },
{ id: 4, children: [8, 9] },
{ id: 9 },
{ id: 3, children: [6, 7] },
{ id: 11, children: [14] },
{ id: 14 },
{ id: 7, children: [12] },
{ id: 12 }
];
输出:
// [
// [ 1, 3, 6 ],
// [ 1, 4, 8, 13 ],
// [ 1, 2, 5, 10 ],
// [ 1, 4, 9 ],
// [ 1, 2, 5, 11, 14 ],
// [ 1, 3, 7, 12 ]
// ]
意思就是从根节点开始遍历多叉树,和单纯的递归遍历不一样的地方是多了回溯。递归一般是判断是否存在某个节点或者对特定节点做一些处理,回溯是在递归的基础上找所有可行解。
编码实现
这道题在 coding 环节我是想着用 DFS 去回溯的,不过当时卡在怎么保存父节点上面,后面面试官给了一个提示说从叶子节点到根结点去访问,当时没太 get 到啥意思,后来想明白了是就是回溯的意思。
function parseArrToTree(arr) {
//
var root = arr.filter(item => item.id === 1)[0]
var ans = []
var combination = []
dfs(root, arr, ans, combination)
return ans
}
function dfs (root = {}, arr = [], ans = [], combination = []) {
debugger
if (!root.children) {
var copy = JSON.parse(JSON.stringify(combination))
copy.unshift(1) // 这里用了个取巧的办法,每次遍历结束把根结点添加到头部
ans.push(copy)
return
}
var children = root.children
for (var i = 0; i < children.length; i++) {
// 获取每个 child
var child = children[i]
// 保存当前存入的 child
combination.push(child)
var _root = arr.filter(item => item.id === child)[0]
dfs(_root, arr, ans, combination)
combination.pop() // 这里是回溯最重要的点:遍历结束后回退到上一个节点
}
}
console.log('ans ===', parseArrToTree(list))