鉴于一棵树,我应该检查它是否对称,或者是否是自己的中心镜像。我错过了一个边缘案例,并且在我的生活中无法弄清楚它是什么。我在CodeFights上遇到的唯一错误是"超出输出限制"
Here's what the example tree looks like
这是主要功能 isTreeSymmetric 将其左分支分配给一个变量,该变量调用 leftBranch 函数并右分支到 rightBranch 函数递归返回一个数组。
我使用两种不同功能的原因是因为它帮助我划分了我的想法,因为在树的左半部分我必须从右到左,反之亦然,因此我没有迷失在一个树洞里。
isTreeSymmetrical中的最后一个return语句然后检查返回的类型值是否为Arrays,后跟一个三元组,它检查左右数组,或者在值不是数组的情况下检查变量lb和rb的相等性。
我一直致力于这种感觉,就像永恒!请帮助。
function isTreeSymmetric(t) {
"use strict";
if(!t || ( (!t.left && !t.right) && t.value)) return true
if(!t.left || !t.right) return false
let left = t.left, right = t.right
let rb = rightBranch(right), lb = leftBranch(left)
console.log(`right branch values are ${rb} | left branch values are ${lb}`)
return Array.isArray( rb || lb ) ?
rb.every( (e, i) => e === lb[i]) :
lb === rb
}
//ON RIGHT BRANCH RETURN CHILDREN LEFT TO RIGHT
function rightBranch(n){
"use strict";
if(!n) return null
let value = n.value
if(!n.left && !n.right) return value
let left = n.left || null, right = n.right || null;
return [value].concat(
rightBranch(left),
rightBranch(right)
)
}
// ON LEFT BRANCH RETURN CHILDREN RIGHT TO LEFT
function leftBranch(n) {
"use strict";
if(!n) return null
let value = n.value
if(!n.left && !n.right) return value
let left = n.left || null, right = n.right || null;
return [value].concat(
leftBranch(right),
leftBranch(left))
}
let t = {
"value": 1,
"left": {
"value": 2,
"left": {
"value": 3,
"left": null,
"right": null
},
"right": {
"value": 4,
"left": null,
"right": null
}
},
"right": {
"value": 2,
"left": {
"value": 4,
"left": null,
"right": null
},
"right": {
"value": 3,
"left": null,
"right": null
}
}
}
console.log(isTreeSymmetric(t)) //true

答案 0 :(得分:1)
我使用两种不同功能的原因是因为它帮助我划分了我的想法,因为在树的左半部分我必须从右到左,反之亦然,因此我没有迷失在一个树洞里。
但是处理树的左侧或右侧根本没什么不同。每个L和R是另一棵树 - 所以你要做的就是比较(l.left, r.left)
和(l.right, r.right)
下面我们有一个递归函数,它创建一个树状的递归过程。一旦比较的false
不相等,它就会短路并返回value
。
我没有使用你创建的树文字,而是创建了一个简单的Node
构造函数来更轻松地构建树节点。这允许我为对称树和非对称树创建测试用例,以验证我们的功能是否正常工作
const isTreeSymmetric = tree => {
const aux = (l, r) => {
if (l === undefined && r === undefined)
return true
else if (l === undefined || r === undefined)
return false
else if (l.value === r.value)
return aux(l.left, r.left) && aux(l.right, r.right)
else
return false
}
return aux(tree.left, tree.right)
}
const Node = (value, left, right) => ({value, left, right})
const tree1 =
Node(1,
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))),
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))))
const tree2 =
Node(1,
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))),
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(6000))))
console.log(isTreeSymmetric(tree1)) // true
console.log(isTreeSymmetric(tree2)) // false

代码重复使用
精明的观察者会注意到上面的aux
函数检查树相等 - 这是一个有用的函数,所以在外面定义它是有意义的isTreeSymmetric
。
这可能是编写isTreeSymmetric
函数的更好方法,因为它更清楚地发生了什么并促进了函数重用
const isTreeEqual = (x, y) => {
if (x === undefined && y === undefined)
return true
else if (x === undefined || y === undefined)
return false
else if (x.value === y.value)
return isTreeEqual(x.left, y.left) && isTreeEqual(x.right, y.right)
else
return false
}
const isTreeSymmetric = tree =>
isTreeEqual(tree.left, tree.right)
const Node = (value, left, right) => ({value, left, right})
const tree1 =
Node(1,
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))),
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))))
const tree2 =
Node(1,
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(5))),
Node(2,
Node(3, Node(4), Node(5)),
Node(3, Node(4), Node(6000))))
console.log(isTreeSymmetric(tree1)) // true
console.log(isTreeSymmetric(tree2)) // false

答案 1 :(得分:0)
我最好使用单个函数来遍历给定树的子节点。在上面的代码中,遍历的顺序是交换值,因此无法检查对称树条件。请检查以下代码,并告诉我它是否适合您。
function isTreeSymmetric(t) {
"use strict";
if(!t || ( (!t.left && !t.right) && t.value)) return true
if(!t.left || !t.right) return false
let left = t.left, right = t.right
let rb = traverseTree(right), lb = traverseTree(left)
return Array.isArray( rb || lb ) ?
rb.every( (e, i) => e === lb[i]) :
lb === rb
}
// ON traverseTree
function traverseTree(n) {
"use strict";
if(!n) return null
let value = n.value
if(!n.left && !n.right) return value
let left = n.left || null, right = n.right || null;
return [value].concat(
traverseTree(left),
traverseTree(right))
}
var tree;
tree = {
value: 1,
left: {
value: 2,
left: {
value: 3
},
right: {
value: 4
}
},
right: {
value: 2,
left: {
value: 3
},
right: {
value: 4
}
}
};
console.log(isTreeSymmetric(tree));
答案 2 :(得分:0)
您实际上并不需要检查节点或将其分组到数组中。就像你和@naomik所做的一样,但是返回isTreeEqual(x.left,y.right)&& isTreeEqual(x.right,y.left)。这会检查值和对称性(因为右侧的右侧分支需要左对齐,左侧分支左侧,左侧右侧分支需要对称,右侧分支左侧)。
代码:
function isTreeSymmetric(t) {
if (!t){
return true
}
return isTreeEqual(t.left, t.right)
}
isTreeEqual = function(x, y) {
if (!x && !y){
return true
}
if (!x || !y){
return false
}
if (x.value === y.value){
return isTreeEqual(x.left, y.right) && isTreeEqual(x.right, y.left)
} else {
return false
}
}
答案 3 :(得分:0)
这里有一个简单的版本,可以通过执行级订单遍历来解决JavaScript中的这个问题,希望对您有所帮助!
var isSymmetric = function(root) {
var levels = levelOrder(root)
for (var x = 1; x < levels.length; x++) {
var level = levels[x]
for (var i = 0, j = level.length-1; i < level.length; i++,j--) {
if (level[i] != level[j]) {
return false
}
}
}
return true
};
var levelOrder = function(node) {
if (node == null) { return []}
var discovered = [];
discovered.push(node)
var levels = levelOrderTraverse(discovered,[])
return levels
}
function levelOrderTraverse(discovered,elms) {
var level = []
for (var i = 0; i < discovered.length; i++) {
if (discovered[i] != null) {
level.push(discovered[i].val)
} else {
level.push("null")
}
}
elms.push(level);
var newlyDiscovered = [];
for (var i = 0; i < discovered.length; i++) {
if (discovered[i] != null) {
if (discovered[i].left != null) {
newlyDiscovered.push(discovered[i].left)
} else {
newlyDiscovered.push(null)
}
if (discovered[i].right != null) {
newlyDiscovered.push(discovered[i].right)
} else {
newlyDiscovered.push(null)
}
}
}
if (newlyDiscovered.length > 0) {
levelOrderTraverse(newlyDiscovered,elms)
}
return elms
}
也可以在my github
上找到