私はインタビューの質問を見ていましたが、最近、右から左に反転するなど、一般的なバイナリツリーを逆にする方法を尋ねる質問に出会いました。
たとえば、バイナリツリーがある場合
6
/ \
3 4
/ \ / \
7 3 8 1
逆にすると作成されます
6
/ \
4 3
/ \ / \
1 8 3 7
この問題を解決する方法について、良い実装を考えることができませんでした。誰でも良いアイデアを提供できますか?
ありがとう
再帰を使用できます:
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);
}
}
コメントに基づいて:
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);
}
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;
}
この質問には興味深い部分がいくつかあります。まず、あなたの言語はJavaであるため、一般的なNodeclass)を持つ可能性が最も高い:
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;
}
....
}
第二に、ノードの左と右のフィールドを変更するか、newノードを作成することにより、反転と呼ばれることもあります。オリジナルですが、その左右の子は「反転」しています。前者のアプローチは 別の回答 に示されていますが、2番目のアプローチはここに示されています:
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);
}
}
データ構造を変更しないという考え方は、 永続的なデータ構造 の背後にある考え方の1つであり、非常に興味深いものです。
私は、ほとんどの答えがヌルポインターの問題に焦点を合わせていないことを見てきました。
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;
}
上記のコードでは、ルートノードの左/右の子がnullでない場合にのみ再帰呼び出しを行っています。最速のアプローチの1つです!
以下のように、左ノードと右ノードを再帰的に交換できます。
// 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