检查JavaScript

时间:2017-04-28 01:30:08

标签: javascript arrays algorithm recursion tree

鉴于一棵树,我应该检查它是否对称,或者是否是自己的中心镜像。我错过了一个边缘案例,并且在我的生活中无法弄清楚它是什么。我在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




4 个答案:

答案 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

上找到