J'étais en train de regarder des questions d'entrevue et je suis récemment tombé sur une question qui vous demandait comment inverser un arbre binaire général, comme le retourner de droite à gauche.
Donc, par exemple, si nous avions l'arbre binaire
6
/ \
3 4
/ \ / \
7 3 8 1
Le renverser créerait
6
/ \
4 3
/ \ / \
1 8 3 7
Je n'ai pas été capable de penser à une bonne implémentation sur la façon de résoudre ce problème. Quelqu'un peut-il offrir de bonnes idées?
Merci
Vous pouvez utiliser la récursivité:
static void reverseTree(final TreeNode root) {
final TreeNode temp = root.right;
root.right = root.left;
root.left = temp;
if (root.left != null) {
reverseTree(root.left);
}
if (root.right != null) {
reverseTree(root.right);
}
}
Basé sur les commentaires:
static void reverseTree(final TreeNode root) {
if (root == null) {
return;
}
final TreeNode temp = root.right;
root.right = root.left;
root.left = temp;
reverseTree(root.left);
reverseTree(root.right);
}
Inverser un arbre binaire dans O (1).
struct NormalNode {
int value;
struct NormalNode *left;
struct NormalNode *right;
};
struct ReversedNode {
int value;
struct ReversedNode *right;
struct ReversedNode *left;
};
struct ReversedNode *reverseTree(struct NormalNode *root) {
return (struct ReversedNode *)root;
}
Il y a deux parties intéressantes à cette question. Premièrement, puisque votre langage est Java, vous avez probablement un nœud générique class, comme ceci:
class Node<T> {
private final T data;
private final Node left;
private final Node right;
public Node<T>(final T data, final Node left, final Node right) {
this.data = data;
this.left = left;
this.right = right;
}
....
}
Deuxièmement, l'inversion, parfois appelée inversion, peut être effectuée soit en mutant les champs gauche et droit du nœud, soit en créant un nœud new identique à l'original mais dont les enfants gauche et droit sont "inversés". La première approche est montrée dans une autre réponse , tandis que la seconde approche est montrée ici:
class Node<T> {
// See fields and constructor above...
public Node<T> reverse() {
Node<T> newLeftSubtree = right == null ? null : right.reverse();
Node<T> newRightSubtree = left == null ? null : left.reverse();
return Node<T>(data, newLeftSubtree, newRightSubtree);
}
}
L'idée de ne pas transformer une structure de données est l'une des idées derrière les structures de données persistantes , qui sont très intéressantes.
J'ai vu que la plupart des réponses ne se concentraient pas sur les problèmes de pointeurs nuls.
public static Node invertBinaryTree(Node node) {
if(node != null) {
Node temp = node.getLeftChild();
node.setLeftChild(node.getRightChild());
node.setRigthChild(temp);
if(node.left!=null) {
invertBinaryTree(node.getLeftChild());
}
if(node.right !=null) {
invertBinaryTree(node.getRightChild());
}
}
return node;
}
Dans le code ci-dessus, nous effectuons des appels récursifs uniquement si l'enfant gauche/droit du nœud racine n'est pas null. C'est l'une des approches les plus rapides!
Vous pouvez échanger récursivement les nœuds gauche et droit comme indiqué ci-dessous;
// helper method
private static void reverseTree(TreeNode<Integer> root) {
reverseTreeNode(root);
}
private static void reverseTreeNode(TreeNode<Integer> node) {
TreeNode<Integer> temp = node.left;
node.left = node.right;
node.right = temp;
if(node.left != null)
reverseTreeNode(node.left);
if(node.right != null)
reverseTreeNode(node.right);
}
import Java.util.LinkedList;
import Java.util.Queue;
public class InvertBinaryTreeDemo {
public static void main(String[] args) {
// root node
TreeNode<Integer> root = new TreeNode<>(6);
// children of root
root.left = new TreeNode<Integer>(3);
root.right = new TreeNode<Integer>(4);
// grand left children of root
root.left.left = new TreeNode<Integer>(7);
root.left.right = new TreeNode<Integer>(3);
// grand right childrend of root
root.right.left = new TreeNode<Integer>(8);
root.right.right = new TreeNode<Integer>(1);
System.out.println("Before invert");
traverseTree(root);
reverseTree(root);
System.out.println("\nAfter invert");
traverseTree(root);
}
// helper method
private static void reverseTree(TreeNode<Integer> root) {
reverseTreeNode(root);
}
private static void reverseTreeNode(TreeNode<Integer> node) {
TreeNode<Integer> temp = node.left;
node.left = node.right;
node.right = temp;
if(node.left != null)
reverseTreeNode(node.left);
if(node.right != null)
reverseTreeNode(node.right);
}
// helper method for traverse
private static void traverseTree(TreeNode<Integer> root) {
Queue<Integer> leftChildren = new LinkedList<>();
Queue<Integer> rightChildren = new LinkedList<>();
traverseTreeNode(root, leftChildren, rightChildren);
System.out.println("Tree;\n*****");
System.out.printf("%3d\n", root.value);
int count = 0;
int div = 0;
while(!(leftChildren.isEmpty() && rightChildren.isEmpty())) {
System.out.printf("%3d\t%3d\t", leftChildren.poll(), rightChildren.poll());
count += 2;
div++;
if( (double)count == (Math.pow(2, div))) {
System.out.println();
count = 0;
}
}
System.out.println();
}
private static void traverseTreeNode(TreeNode<Integer> node, Queue<Integer> leftChildren, Queue<Integer> rightChildren) {
if(node.left != null)
leftChildren.offer(node.left.value);
if(node.right != null)
rightChildren.offer(node.right.value);
if(node.left != null) {
traverseTreeNode(node.left, leftChildren, rightChildren);
}
if(node.right != null) {
traverseTreeNode(node.right, leftChildren, rightChildren);
}
}
private static class TreeNode<E extends Comparable<E>> {
protected E value;
protected TreeNode<E> left;
protected TreeNode<E> right;
public TreeNode(E value) {
this.value = value;
this.left = null;
this.right = null;
}
}
}
Before invert
Tree;
*****
6
3 4
7 3 8 1
After invert
Tree;
*****
6
4 3
1 8 3 7