【问题标题】:I am looking at an iterative solution of checking whether a tree is symmetric我正在研究检查树是否对称的迭代解决方案
【发布时间】:2020-07-21 13:49:16
【问题描述】:

我有以下代码:

class TreeNode {
    constructor(val) {
        this.val = val
        this.left = this.right = null
    }
}

const isSymmetric = root => {
    if (!root) return true
    let stackP = []
    let stackQ = []
    let currentP = root
    let currentQ = root

    while ((currentP && currentQ) || (stackP.length && stackQ.length)) {

        while (currentP) {
            stackP.push(currentP)
            currentP = currentP.left
        }
        while (currentQ) {
            stackQ.push(currentQ)
            currentQ = currentQ.right
        }

        console.log(stackP, stackQ, 'after push')

        currentP = stackP.pop()
        currentQ = stackQ.pop()
        console.log(stackP, stackQ, 'after 1 iterative pop')

        if ((currentP.val !== currentQ.val) || (stackP.length !== stackQ.length)) return false
        console.log(currentP, currentQ, 'after if statement')

        // confused as to why we are setting it to the opposite here
        currentP = currentP.right
        currentQ = currentQ.left


        console.log(currentP, currentQ, 'after opp DECLARATION')
    }
    return true
}

//example 1
const tree1 = new TreeNode(1)
tree1.left = new TreeNode(2)
tree1.right = new TreeNode(2)

tree1.left.left = new TreeNode(3)
tree1.left.right = new TreeNode(4)

tree1.right.left = new TreeNode(4)
tree1.right.right = new TreeNode(3)

//example 2
const tree2 = new TreeNode(1)
tree2.left = new TreeNode(2)
tree2.right = new TreeNode(2)

tree2.left.right = new TreeNode(3)

tree2.right.right = new TreeNode(3)

console.log(isSymmetric(tree1));
console.log(isSymmetric(tree2));

但是,我对以下两行感到困惑:

currentP = currentP.right
currentQ = currentQ.left

我不确定为什么要这样做。我尝试跟随控制台日志记录,但无法跟随。我希望currentP 能够按照设置在左侧的原始模式保持自身,但似乎在弹出PQ 之后它们现在正在向右移动。我不明白为什么。谁能澄清一下?

假设我们有以下树

   A 
  / \ 
 B   B 
/ \ / \ 
C D D C 

跟踪 currentPcurrentQ 应该给出以下值 A、B、C、C、null、B、D、null、A。但是当我们通过逻辑到达 A 时,似乎我们处于无限循环。除非我没有正确跟踪它。在我们将 currentPcurrentQ 声明为“A”之后,我们应该再次进入 while 循环,基本上将 B 和 C 再次推回,我是否遗漏了什么?

【问题讨论】:

  • 只需将根的左右子树视为两棵不同的树。然后,同时遍历两者,如果它们在任何时候发散,你就有了答案。这就像一次在两棵树中执行 DFS,如果在某个时刻一个节点为空而另一个不是,那么您会发现不同之处。您可以迭代地执行此操作,但递归似乎更容易实现。

标签: javascript algorithm tree iteration


【解决方案1】:

鉴于这棵树:

   A
  / \
 B   C
/ \ / \
D E F G

首先它一直走到左边 (stackP = B, D) 堆叠它们,然后走到右边 (stackQ = C, G)。然后比较最后的叶子(D,G)。然后拿他们的兄弟姐妹(E,F)比较 - 这就是你在谈论的部分。然后弹出他们的父母(B,C)并进行比较。

这是带有一些调试信息的程序,可以让您更好地了解它在做什么:

class TreeNode {
  constructor(val) {
    this.val = val;
    this.left = this.right = null;
  }
}

function serialize(arr) {
  return arr.map(e => e.val).join(",");
}

const isSymmetric = (root) => {
  if (!root) return true;
  let stackP = [];
  let stackQ = [];
  let currentP = root;
  let currentQ = root;

  while ((currentP && currentQ) || (stackP.length && stackQ.length)) {
    while (currentP) {
      stackP.push(currentP);
      console.log(`Pushing ${currentP.val} to sP=[${serialize(stackP)}]`)
      currentP = currentP.left;
    }
    while (currentQ) {
      stackQ.push(currentQ);
      console.log(`Pushing ${currentQ.val} to sQ=[${serialize(stackQ)}]`)
      currentQ = currentQ.right;
    }

    currentP = stackP.pop();
    currentQ = stackQ.pop();

    console.log(`Comparing cP=${currentP.val} cQ=${currentQ.val} sP=[${serialize(stackP)}] sQ=[${serialize(stackQ)}]`);

    if (currentP.val !== currentQ.val || stackP.length !== stackQ.length)
      return false;

    // confused as to why we are setting it to the opposite here
    currentP = currentP.right;
    currentQ = currentQ.left;

    console.log(`Looping   cP=${currentP ? currentP.val : "null"} cQ=${currentQ ? currentQ.val : "null"} sP=[${serialize(stackP)}] sQ=[${serialize(stackQ)}]`);
  }
  return true;
};

//example 1
const tree1 = new TreeNode(1)
tree1.left = new TreeNode(2)
tree1.right = new TreeNode(2)

tree1.left.left = new TreeNode(3)
tree1.left.right = new TreeNode(4)

tree1.right.left = new TreeNode(4)
tree1.right.right = new TreeNode(3)

//example 2
const tree2 = new TreeNode(1)
tree2.left = new TreeNode(2)
tree2.right = new TreeNode(2)

tree2.left.right = new TreeNode(3)

tree2.right.right = new TreeNode(3)

console.log(isSymmetric(tree1));
console.log(isSymmetric(tree2));

【讨论】:

  • 跟踪 'currentP' 和 'currentQ' 应该给出以下值 A、B、C、C、null、B、D、null、A。但是当我们通过逻辑到达 A 时似乎我们处于无限循环中。除非我没有正确跟踪它。在我们将 'currentP' 和 'currentQ' 声明为 'A' 之后,我们应该再次进入 while 循环,基本上将 B 和 C 再次推回,我是否遗漏了什么?
  • 将树添加到问题描述中
  • 更新了一些更好的调试信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 2013-02-22
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多