← Static tasks

894. All Possible Full Binary Trees

leetcode medium

#csharp#leetcode#medium#tree#two-pointers

Task

Учитывая целое число n, верните список всех возможных полных бинарных деревьев с узлами. Каждый узел каждого дерева в ответе должен иметь Node.val == 0. Каждый элемент ответа является корневым узлом одного возможного дерева. Вы можете вернуть конечный список деревьев в любом порядке. Полное бинарное дерево - это бинарное дерево, в котором каждый узел имеет ровно 0 или 2 дочерних.

Пример:

Input: n = 7

Output: [[0,0,0,null,null,0,0,null,null,0,0],[0,0,0,null,null,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,null,null,null,null,0,0],[0,0,0,0,0,null,null,0,0]]

C# solution

matched/original
using System;
using System.Collections.Generic;
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
public class Solution {
    public IList<TreeNode> AllPossibleFBT(int n) {
        if (n % 2 == 0) return new List<TreeNode>();
        if (n == 1) return new List<TreeNode> { new TreeNode(0) };
        
        List<TreeNode> result = new List<TreeNode>();
        for (int i = 1; i < n; i += 2) {
            var leftTrees = AllPossibleFBT(i);
            var rightTrees = AllPossibleFBT(n - 1 - i);
            foreach (var left in leftTrees) {
                foreach (var right in rightTrees) {
                    TreeNode root = new TreeNode(0, left, right);
                    result.Add(root);
                }
            }
        }
        return result;
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
class Solution {
public:
    public IList<TreeNode> AllPossibleFBT(int n) {
        if (n % 2 == 0) return new List<TreeNode>();
        if (n == 1) return new List<TreeNode> { new TreeNode(0) };
        
        List<TreeNode> result = new List<TreeNode>();
        for (int i = 1; i < n; i += 2) {
            var leftTrees = AllPossibleFBT(i);
            var rightTrees = AllPossibleFBT(n - 1 - i);
            foreach (var left in leftTrees) {
                foreach (var right in rightTrees) {
                    TreeNode root = new TreeNode(0, left, right);
                    result.push_back(root);
                }
            }
        }
        return result;
    }
}

Java solution

matched/original
import java.util.*;

class TreeNode {
    int val;
    TreeNode left, right;
    TreeNode(int x) { val = 0; }
}

class Solution {
    public List<TreeNode> allPossibleFBT(int n) {
        if (n % 2 == 0) return new ArrayList<>();
        if (n == 1) return Arrays.asList(new TreeNode(0));
        
        List<TreeNode> result = new ArrayList<>();
        for (int i = 1; i < n; i += 2) {
            List<TreeNode> leftTrees = allPossibleFBT(i);
            List<TreeNode> rightTrees = allPossibleFBT(n - 1 - i);
            for (TreeNode left : leftTrees) {
                for (TreeNode right : rightTrees) {
                    TreeNode root = new TreeNode(0);
                    root.left = left;
                    root.right = right;
                    result.add(root);
                }
            }
        }
        return result;
    }

JavaScript solution

matched/original
function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val)
    this.left = (left===undefined ? null : left)
    this.right = (right===undefined ? null : right)
}

var allPossibleFBT = function(n) {
    if (n % 2 === 0) {
        return [];
    }
    if (n === 1) {
        return [new TreeNode(0)];
    }
    
    const result = [];
    for (let i = 1; i < n; i += 2) {
        const leftTrees = allPossibleFBT(i);
        const rightTrees = allPossibleFBT(n - 1 - i);
        for (const left of leftTrees) {
            for (const right of rightTrees) {
                result.push(new TreeNode(0, left, right));
            }
        }
    }
    return result;

Python solution

matched/original
public class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?
    public init() { self.val = 0; self.left = nil; self.right = nil }
    public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil }
    public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
        self.val = val
        self.left = left
        self.right = right
    }
}

func allPossibleFBT(_ n: Int) -> [TreeNode?] {
    if n % 2 == 0 {
        return []
    }
    if n == 1 {
        return [TreeNode(0)]
    }
    
    var result = [TreeNode]()
    for i in stride(from: 1, to: n, by: 2) {
        let leftTrees = allPossibleFBT(i)
        let rightTrees = allPossibleFBT(n - 1 - i)
        for left in leftTrees {
            for right in rightTrees {
                result.append(TreeNode(0, left, right))
            }
        }
    }
    return result

Explanation

Algorithm

Если n четное, вернуть пустой список, так как полное бинарное дерево не может иметь четное количество узлов.

Если n == 1, вернуть дерево с одним узлом. Для всех возможных значений i от 1 до n-1 с шагом 2: Создать левое поддерево с i узлами. Создать правое поддерево с n-1-i узлами. Объединить все комбинации левого и правого поддеревьев с новым корнем, добавив их в список результатов.

Вернуть список результатов.

😎