it-swarm.com.de

Prüfen Sie, ob es sich bei einem binären Baum um ein Spiegelbild oder um ein symmetrisches Modell handelt

Was ist der grundlegende Algorithmus zum Testen, ob ein Baum symmetrisch ist. Da es sich um einen binären Baum handelt, würde ich davon ausgehen, dass es sich um eine rekursive Definition von Sorten handelt

Die formale Frage ist unten:

Ein binärer Baum ist ein Spiegelbild von sich selbst, wenn sein linker und rechter Unterbaum identische Spiegelbilder sind, d. H.

  1
 / \
2   2

WAHR

   1
  / \
 2   2
  \
   3

FALSE

     1
   /   \
  2     2
 / \   / \
4   3 3   4

WAHR

       1
     /   \
    2     2 
   / \   / \
  3   4 3   4

FALSE

       1
     /   \
    2     2
   /       \
  3         3

WAHR

Definieren Sie in einer Programmiersprache Ihrer Wahl eine BTree-Klasse/C-Struktur und eine zugehörige Methode, um zu überprüfen, ob der Baum ein Spiegelbild ist. Bei statisch typisierten Sprachen können Sie davon ausgehen, dass Knotenwerte nur Ganzzahlen sind.

Class/structure definition
BTree {
  BTree left;
  BTree right;
  int value;
}

Angenommen, die Wurzel der Baumstruktur wird vom Aufrufer verfolgt und die Funktion isMirror () wird darin aufgerufen.

Wenn Sie eine Klasse definieren, stellen Sie sicher, dass Sie einen Konstruktor ohne Argumente und Getter/Setter-Methoden bereitstellen, wenn Datenelemente nicht öffentlich zugänglich sind.

50

Wie wäre es, mirrorEquals (root.left, root.right) für die folgende Funktion aufzurufen: -

boolean mirrorEquals(BTree left, BTree right) {
  if (left == null || right == null) return left == null && right == null;
  return left.value == right.value
     && mirrorEquals(left.left, right.right)
     && mirrorEquals(left.right, right.left);
}

Vergleichen Sie grundsätzlich den linken Teilbaum und den umgekehrten rechten Teilbaum, wobei eine imaginäre Inversionslinie über den Stamm gezogen wird.

103
gvijay

Lösung 1 - rekursiv:

bool isMirror(BinaryTreeNode *a, BinaryTreeNode *b)
{
    return (a && b) ?  
        (a->m_nValue==b->m_nValue 
        && isMirror(a->m_pLeft,b->m_pRight) 
        && isMirror(a->m_pRight,b->m_pLeft)) :  
    (a == b);
}
bool isMirrorItselfRecursively(BinaryTreeNode *root) 
{
    if (!root)
        return true;

    return isMirror(root->m_pLeft, root->m_pRight);
}

Lösung 2 - iterativ:

bool isMirrorItselfIteratively(BinaryTreeNode *root) 
{
    /// use single queue
    if(!root) return true;
    queue<BinaryTreeNode *> q;
    q.Push(root->m_pLeft);
    q.Push(root->m_pRight);
    BinaryTreeNode *l, *r;
    while(!q.empty()) {
        l = q.front();
        q.pop();
        r = q.front();
        q.pop();
        if(l==NULL && r==NULL) continue;
        if(l==NULL || r==NULL || l->m_nValue!=r->m_nValue) return false;
        q.Push(l->m_pLeft);
        q.Push(r->m_pRight);
        q.Push(l->m_pRight);
        q.Push(r->m_pLeft);
    }

    return true;
}
9
herohuyongtao

Die rekursive Lösung von @gvijay ist sehr klar und hier eine iterative Lösung.

Überprüfen Sie jede Zeile des Baums von oben nach unten und prüfen Sie, ob die Werte ein Palindrom sind. Wenn sie alle sind, dann ist es ein Spiegel. Sie müssen einen Algorithmus implementieren, um jede Zeile zu besuchen, und für spärliche Bäume Nullwerte angeben. Im Pseudocode:

boolean isMirror(BTree tree) {
  foreach (List<Integer> row : tree.rows() {
    if (row != row.reverse()) return false;
  }
  return true;
}

Der Trick besteht darin, den Algorithmus so zu entwerfen, dass er die Zeilen eines Baums wiederholt, wobei berücksichtigt wird, dass spärliche Bäume als Platzhalter Nullwerte haben sollten. Diese Java-Implementierung scheint in Ordnung zu sein:

public static boolean isMirror(BTree root) {
  List<BTree> thisRow, nextRow;
  thisRow = Arrays.asList(root);
  while (true) {
    // Return false if this row is not a palindrome.
    for (int i=0; i<thisRow.size()/2; i++) {
      BTree x = thisRow.get(i);
      BTree y = thisRow.get(thisRow.size()-i-1);
      if ((x!=null) && (y!=null)
          && (x.value != y.value))
        return false;
      if (((x==null) && (y!=null))
          || (x!=null) && (y==null))
        return false;
    }
    // Move on to the next row.
    nextRow = new ArrayList<BTree>();
    for (BTree tree : thisRow) {
      nextRow.add((tree==null) ? null : tree.lt);
      nextRow.add((tree==null) ? null : tree.rt);
    }
    boolean allNull = true;
    for (BTree tree : nextRow) {
      if (tree != null) allNull = false;
    }
    // If the row is all empty then we're done.
    if (allNull) return true;
    thisRow = nextRow;
  }
}
4
maerics

Rekursive und iterative Lösungen in Java unter Verwendung der oben beschriebenen Ansätze

Rekursiv  

public Boolean isSymmetric(TreeNode root) {
    if (root == null) {
        return true;
    }

    return isSymmetricInternal(root.left, root.right);
}

private Boolean isSymmetricInternal(TreeNode leftNode,
        TreeNode rightNode) {

    boolean result = false;

    // If both null then true
    if (leftNode == null && rightNode == null) {
        result = true;
    }

    if (leftNode != null && rightNode != null) {
        result = (leftNode.data == rightNode.data)
                && isSymmetricInternal(leftNode.left, rightNode.right)
                && isSymmetricInternal(leftNode.right, rightNode.left);
    }

    return result;
}

Iterativ Verwendung von LinkedList als Queue 

private Boolean isSymmetricRecursive(TreeNode root) {
    boolean result = false;

    if (root == null) {
        return= true;
    }

    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root.left);
    queue.offer(root.right);

    while (!queue.isEmpty()) {
        TreeNode left = queue.poll();
        TreeNode right = queue.poll();

        if (left == null && right == null) {

            result = true;

        }
        else if (left == null || 
                right == null || 
                left.data != right.data) {
            // It is required to set result = false here
            result = false;
            break;
        }

        else if (left != null && right != null) {
            queue.offer(left.left);
            queue.offer(right.right);

            queue.offer(left.right);
            queue.offer(right.left);
        }
    }

    return result;
}

Testfall  

    @Test
public void testTree() {

    TreeNode root0 = new TreeNode(1);
    assertTrue(isSymmetric(root0));
    assertTrue(isSymmetricRecursive(root0));

    TreeNode root1 = new TreeNode(1, new TreeNode(2), new TreeNode(2));
    assertTrue(isSymmetric(root1));
    assertTrue(isSymmetricRecursive(root1));

    TreeNode root2 = new TreeNode(1,
            new TreeNode(2, null, new TreeNode(3)), new TreeNode(2));
    assertFalse(isSymmetric(root2));
    assertFalse(isSymmetricRecursive(root2));

    TreeNode root3 = new TreeNode(1, new TreeNode(2, new TreeNode(4),
            new TreeNode(3)), new TreeNode(2, new TreeNode(3),
            new TreeNode(4)));
    assertTrue(isTreeSymmetric(root3));
    assertTrue(isSymmetricRecursive(root3));

    TreeNode root4 = new TreeNode(1, new TreeNode(2, new TreeNode(3),
            new TreeNode(4)), new TreeNode(2, new TreeNode(3),
            new TreeNode(4)));
    assertFalse(isSymmetric(root4));
    assertFalse(isSymmetricRecursive(root4));
}

Baumknoten Klasse 

public class TreeNode {

int data;

public TreeNode left;
public TreeNode right;

public TreeNode(int data){
    this(data, null, null);
}

public TreeNode(int data, TreeNode left, TreeNode right)
{
    this.data = data;
    this.left = left;
    this.right = right;
}
}
4
Rohit

Hier ist eine C++ - Lösung pro gvijay

bool isMirrorTree(BTnode* LP, BTnode* RP)
{
    if (LP == NULL || RP == NULL) // if either is null check that both are NULL
    { 
        return ( LP == NULL && RP == NULL );
    } 
    // check that data is equal and then recurse
    return LP->data == RP->data && 
           isMirrorTree( LP->left, RP->right ) && 
           isMirrorTree( LP->right, RP->left );
}
2
user656925

EDIT

Wie in den Kommentaren darauf hingewiesen wurde, schlug meine erste Version des Algorithmus für bestimmte Eingaben fehl. Ich werde das Rad nicht neu erfinden, ich werde nur eine Python-Antwort mit dem korrekten Algorithmus @gvijay bereitstellen. Zuerst eine Darstellung für den Binärbaum:

class BTree(object):
    def __init__(self, l, r, v):
        self.left  = l
        self.right = r
        self.value = v
    def is_mirror(self):
        return self._mirror_equals(self.left, self.right)
    def _mirror_equals(self, left, right):
        if left is None or right is None:
            return left is None and right is None
        return (left.value == right.value
                and self._mirror_equals(left.left, right.right)
                and self._mirror_equals(left.right, right.left))

Ich habe den obigen Code mit allen Beispielbäumen in der Frage und den Bäumen getestet, die falsche Ergebnisse zurückgaben, wie in den Kommentaren erwähnt. Nun sind die Ergebnisse für alle Fälle korrekt:

root1 = BTree(
    BTree(None, None, 2),
    BTree(None, None, 2),
    1)
root1.is_mirror() # True

root2 = BTree(
    BTree(None, BTree(None, None, 3), 2),
    BTree(None, None, 2),
    1)
root2.is_mirror() # False

root3 = BTree(
    BTree(
        BTree(None, None, 4),
        BTree(None, None, 3),
        2),
    BTree(
        BTree(None, None, 3),
        BTree(None, None, 4),
        2),
    1)
root3.is_mirror() # True

root4 = BTree(
    BTree(
        BTree(None, None, 3),
        BTree(None, None, 4),
        2),
    BTree(
        BTree(None, None, 3),
        BTree(None, None, 4),
        2),
    1)
root4.is_mirror() # False

root5 = BTree(
    BTree(BTree(None, None, 3), None, 2),
    BTree(None, BTree(None, None, 3), 2),
    1)
root5.is_mirror() # True

root6 = BTree(BTree(None, None, 1), None, 1)
root6.is_mirror() # False

root7 = BTree(BTree(BTree(None, None, 1), None, 2), None, 1)
root7.is_mirror() # False
2
Óscar López

Wenn jemand eine schnelle Version benötigt, ist hier eine.

Ein anderer Ansatz wäre, einfach einen der Teilbäume zu invertieren und die zwei resultierenden Teilbäume auf einfache Weise zu vergleichen.

func compareTrees(left: TreeNode?, right: TreeNode?) -> Bool {
    var res = false
    if left == nil && right == nil {return true}
    if left != nil && right != nil {
        res = left!.val == right!.val &&
              compareTrees(left!.left, right: right!.left) &&
              compareTrees(left!.right, right: right!.right)
    }
    return res
}

func invertTree(node: TreeNode?) {
    if node == nil {return}

    var tmp = node!.left
    node!.left = node!.right
    node!.right = tmp

    invertTree(node!.left)
    invertTree(node!.right)
}

// and run it as:
if root == nil {print("Y")}
invertTree(root!.right)
compareTrees(root!.left, right: root!.right) ? print("Y") : print("N")
1
aquio

Unten ist die Lösung in Bezug auf C-COde

isMirror(root)
{ 
Symmetric(root->left, root->right);
}

Symmetric(root1,root2)
{
 if( (root1->left EX-NOR root2->right) && (root1->right EX-NOR root2->left) && (root1->value==root2->value) )        
//exnor operation will return true if either both present or both not present 
// a EX-NOR b =(!a && !b) || (a && b))
        {
    Symmetric(root1->left, root2->right);
    Symmetric(root1->right, root2->left);
        }    
else return false;
}
1

öffentliche Klasse SymmetricTree {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    //int[] array = {1,2,2,3,4,4,3};
    /*
     *                  1
     *                 / \
     *                /   \
     *               /     \
     *              2       2
     *             / \     / \
     *            /   \   /   \
     *           3     4 4     3
     * 
     * */
    //int[] array = {1,2};
    BinaryTree bt=new BinaryTree();
    bt.data=1;
    bt.left = new BinaryTree(2);
    bt.right = new BinaryTree(2);
    bt.left.right = new BinaryTree(3);
    bt.right.right = new BinaryTree(3);
    //bt=BinaryTree.buildATree(bt, array);
    System.out.print(isSymmetric(bt));
    BinaryTree.inOrderTraversal(bt);
}
public static boolean isSymmetric(BinaryTree root){
    if(root==null)
        return true;
    return isSymmetricLR(root.left,root.right);
}
public static boolean isSymmetricLR(BinaryTree left, BinaryTree right){
    if(left == null && right == null)
        return true;
    if(left!=null && right!=null)
        return (left.data == right.data) &&
                (isSymmetricLR(left.left, right.right)) &&
                (isSymmetricLR(left.right, right.left));
    return false;
}

}

0
Mohit Motiani

Ich dachte, ich würde eine Lösung in Python hinzufügen, die für manche Menschen leichter verständlich ist als für andere Ansätze. Die Idee ist:

  1. fügen Sie +1 zu dem Wert hinzu, der vom linken untergeordneten Element zurückgegeben wird.
  2. addiere -1 zu dem vom rechten Kind zurückgegebenen Wert.
  3. l+r an das übergeordnete Element zurückgeben

Wenn also l+r == 0 für einen Knoten in der Baumstruktur gilt, ist der an diesem Knoten verankerte Teilbaum symmetrisch. Daher ist der gesamte Baum nur dann symmetrisch, wenn l+r == 0 im Stammverzeichnis ist.

def check(root):
    l = check(root.left)+1 if root.left else 0
    r = check(root.right)-1 if root.right else 0
    return l+r

def is_symmetric(root):
    return root is not None and check(root) == 0
0
Wahab Ali

mit Python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def helper(root1, root2):
            if not root1 and not root2: return True
            if not root1 or not root2: return False            
            if root1.val != root2.val: return False
            if helper(root1.left, root2.right): return helper(root1.right, root2.left)
            return  False
        return helper(root, root)
0
MdNazmulHossain

Etwas andere Herangehensweise.

Wie wäre es, wenn Sie den binären Baum durchlaufen, um alle Inhalte in einer Datenstruktur wie ein String/Array zu speichern?.

Wenn der Durchlauf abgeschlossen ist, prüfen Sie, ob die Elemente in Ihrem Array ein Palindrom bilden Nicht so effizient wie der Raum (Rekursion erfordert O (log (n)), diese Methode tales O(n)) das wird auch funktionieren.

0
user2884123

Iterative Lösung mit etwas anderem Ansatz in Python. Verwenden Sie queue1, um linke Kinder in der Reihenfolge von links nach rechts zu speichern, und queue2, um rechte Kinder in der Reihenfolge von rechts nach links zu speichern und auf Gleichheit zu vergleichen. 

def isSymmetric(root):
    if not root:
        return True
    if not (root.left or root.right):
        return True
    q1 = collections.deque([root.left])
    q2 = collections.deque([root.right])
    while q1 and q2:
        n1 = q1.popleft()
        n2 = q2.popleft()
        if n1 is None and n2 is None:
            continue
        if (n1 is None) ^ (n2 is None):
            return False
        if n1.val != n2.val:
            return False
        q1.append(n1.left)
        q1.append(n1.right)
        q2.append(n2.right)
        q2.append(n2.left)
    if not (q1 and q2):
        return True
    return False
0
Bilal