我正在处理Atlassian的plantyyourcode挑战。我在4.1级。我是个新手。我知道树,因为关于这个问题,当在递归函数中发送树的节点作为参数时,它们由变量接收,而不是引用到原始树。
在递归之后的最终返回值中,我不断地得到未定义的值。我无法解决这个问题。必须对原始树进行编辑,在这种情况下,必须对其进行修剪。
我在这个挑战上坚持了好几天。我已经尝试了我阅读的方法,观看了所有关于这方面的视频,我即将放弃这个级别的挑战。在这之后我只有2个级别,我想进入他们配备。我需要知道正确答案背后的原因,以及我的代码哪里出错了。
这就是我一直在学习、参与挑战和解决问题的方式。对我来说,学习很重要。我对此很认真。我希望得到一个答案来加强我的理解。
你能帮我一下吗?
谢谢。
问:
编写一个函数,在你修剪了所有不健康的节点后,返回你的新根系统,这些节点下面没有健康的节点。
提供的提示:
- 我们有一个二叉树形式的根结构,其中值0是不健康的,1是健康的。空值表示节点位置为空。节点n的子树是n,加上作为n的后代的每个节点
二叉树节点的定义:
- @param{integer}数据-0或1
- @param{Node}left-子树或null表示无左分支
- @param{Node}right-子树或null表示无右分支
function Node(data, left, right) { this.data = data === undefined ? 0 : data; this.left = left === undefined ? null : left; this.right = right === undefined ? null : right; }
-
完成以下确定要修剪哪些节点的操作,以便修剪所有没有健康节点作为子节点的不健康节点并返回结果。将修剪的节点设置为null。
-
@param{Node}root-表示植物根系统的二进制树数据
-
@return{Node}-表示植物修剪后的根系的二叉树数据
我的代码:
function pruneRoots(root) {
const removeNode = function(node) {
if (node === null) {
return null;
}
if (node.data === 0) {
if(node.left && node.right){
if(node.left.data === 0 && node.right.data === 0)
{
return null;
}
}
if(node.right && node.right !== null){
node.right = removeNode(node.right);
}
if(node.left && node.left !== null){
node.left = removeNode(node.left);
}
} else if(node.data === 1){
if(node.right && node.right !== null){
node.right = removeNode(node.right);
}
if(node.left && node.left != null){
node.left = removeNode(node.left);
}}
return node
}
var a = removeNode(root);
console.log(a); //or return a
}
//function call, the root is structured as shown in the argument passed.
pruneRoots({
"data": 1,
"left": null,
"right": {
"data": 0,
"left": {
"data": 0,
"left": null,
"right": null
},
"right": {
"data": 0,
"left": null,
"right": null
}
}
});
代码中的注释揭示了一些误解。
例如,下面的注释并没有描述下一行代码在做什么:
// node has no children
if (node.left && node.right){
上面的if
条件实际上是在测试node
是否有两个孩子!CCD_ 3是";truthy;当它是对象(即节点(时的值;falsy";当它是CCD_ 4时。因此,您正在测试node.left
和node.right
是否都不是null
(因为这是它们在这种情况下唯一可能的"falsy"值(。
以下注释并不总是正确的:可能是节点只有一个右子节点,但没有一个左子节点——一个if
条件可能是正确的,而另一个则不是。
// node has two children
if(node.right && node.right !== null) {
你可以改进的另一件事:
console.log(a) //since its on my code editor
//otherwise return a, for the main challenge page
你应该一直在这里return
。出于调试目的执行console.log
是可以的,但在测试时也要确保执行return
。
逻辑
你的算法中有一个逻辑错误:
if (node.left && node.right){
if(node.left.data === 0 && node.right.data === 0) {
return null
}
}
这是不对的,因为node.left.left
仍然可以有一个值1(即健康(,所以返回null
是错误的。这里的关键见解是,您应该首先对node.left
、node.right
和执行递归调用,然后检查这些节点是否因此而被修剪。如果是这样的话,那么您只能决定同时修剪当前的node
(并返回null
(。
递归
您制作了一个嵌套函数来执行递归。但与递归使用主pruneRoots
函数相比,它确实没有任何优势:它接受相同类型的参数并返回相同类型。您还可以递归地使用pruneRoots
。
已更正
所以这里有一个修正版本:
function pruneRoots(root) {
if (root === null) {
return null;
}
// First perform the recursive pruning
root.left = pruneRoots(root.left);
root.right = pruneRoots(root.right);
// Now we can be sure that if a child still exists,
// there must be a healthy node in its subtree
if (root.data === 0 && !root.left && !root.right) { // Not healthy and no children
return null;
}
// In all other cases, don't prune the node
return root;
}
let result = pruneRoots({
"data": 1,
"left": null,
"right": {
"data": 0,
"left": {
"data": 0,
"left": null,
"right": null
},
"right": {
"data": 0,
"left": null,
"right": null
}
}
});
console.log(result);