Unfortunately i am stuck at the same point. Did you figure it out SF? How serialization of ternary tree works?
Really struggling with this concept, can the editors please expand on this section?
def ternary_tree_paths(root: Node) -> List[str]:
# WRITE YOUR BRILLIANT CODE HERE
paths = []
helper_dfs(root, "", paths)
return paths
def helper_dfs(node, path, paths):
path += str(node.val)
if not node.children:
paths.append(path)
return
for child in node.children:
helper_dfs(child, path + "->", paths)
hey, we added the step-by-step visualization for the dfs call stack. anything else you donāt understand and would like to clarify?
the question is essentially the same as the questions in the dfs section. the new thing is the push and pop/space saving part, which we added a visualization. let me know if thereās anything else youād like to see
In the python solution if condition is surplus
dfs on each non-null child
for child in root.children:
if child is not None:
dfs(child, path + [str(root.val)], res)
I think this āif all(c is None for c in root.children)ā could be simplified to āif not root.childrenā
Before I looked at the included solution, I came up with a short and simple Java one that passes. Updated with a space-saving version that just instantiates one ArrayList
.
public static List<String> ternaryTreePaths(Node<Integer> root) {
List<String> paths = new ArrayList<>();
return buildTernaryTreePaths(root, paths, "");
}
private static List<String> buildTernaryTreePaths(Node<Integer> root, List<String> paths, String path) {
if (root == null) return paths;
path = path + root.val;
if (root.children.size() == 0) {
paths.add(path);
}
for (Node child : root.children) {
buildTernaryTreePaths(child, paths, path + "->");
}
return paths;
}
Hi,
hereās my solution. Lemme know if it is indeed correct,
public static ArrayList<String> dfs(Node<Integer> node, String path, ArrayList<String> result) {
if (node == null) {
return result;
}
path += node.val;
if (node.children.isEmpty()) {
result.add(path);
} else {
for (Node<Integer> child : node.children) {
dfs(child, path+"->", result);
}
}
return result;
}
public static ArrayList<String> ternaryTreePaths(Node<Integer> root) {
ArrayList<String> res = new ArrayList<String>();
res = dfs(root, "", res);
//System.out.println("res is " + res.toString());
return res;
}
For mods, something that could help is to show people how to use the rich text formatting, especially on using the </>
button whenever they enter code. Seems like most users donāt know
Contributing my Java solution that passes the tests and follows similar logic.
public static List<String> ternaryTreePaths(Node<Integer> root) {
List<String> paths = new ArrayList<>();
if (root == null) return paths;
List<String> parentValues = new ArrayList<>();
ternaryTreePaths(root, paths, parentValues);
return paths;
}
private static void ternaryTreePaths(Node<Integer> root, List<String> paths, List<String> parentVals) {
parentVals.add(root.val.toString());
for (AlgoMonsterMultiNode<Integer> child : root.children) {
ternaryTreePaths(child, paths, parentVals);
}
String currentPath = String.join("->", parentVals);
if (root.children.isEmpty()) { // is leaf
paths.add(currentPath);
}
// remove self
parentVals.remove(parentVals.size() - 1);
}
Explanation:
I originally used a Deque#pollLast
(this interface was recommended in previous sections) to hold state and behave as a Stack, but ultimately used ArrayList
as the Stack instead so that String.join
could be compatible with it.
I inadvertently figured out Stacks work well with DFS by doing previous practice problems, but I wish it was actually mentioned as a solution. Ironically Stacks were not really needed until now. I only stumbled upon Stacks as a solution to hold state.
Easy to Follow Readble Java Code
public static List<String> ternaryTreePaths(Node<Integer> root) {
// WRITE YOUR BRILLIANT CODE HERE
List<String> output = new ArrayList<>();
dfs(root, new StringBuilder(), output);
return output;
}
public static void dfs(Node<Integer> root, StringBuilder path, List<String> output){
// we have reached end path add builder to output exit out recursion
if (root.children.size() == 0){
output.add(path.toString());
return;
}
// add node to path
path.append(root.val);
// iter through children recurse through
for (Node<Integer> child : root.children){
// make new string builder
StringBuilder str = new StringBuilder();
str.append(path).append("->");
dfs(child, str, output);
}
}
Minor tweak to the Alogexpert solution. Found it more readable for a beginner with backtracking like me
def ternary_tree_paths(root: Node) -> List[str]:
res = []
def dfs(node, path, res):
if not node: return
if not node.children:
res.append('->'.join(path) + '->' + str(node.val))
return
for child in node.children:
if child is not None:
dfs(child, path + [str(node.val)], res)
res = []
if root: dfs(root, [], res)
return res
If anyone could provide some feedback on my JS solution, Iād appreciate it.
function ternaryTreePath(root, prePath, paths) {
if (root.children.length == 0) {
paths.push(prePath + `${root.val}`);
}
for (const child of root.children) {
ternaryTreePath(child, prePath + `${root.val}->`, paths);
}
}
function ternaryTreePaths(root) {
const paths = [];
if (!root || root.children.length == 0) {
return res;
}
ternaryTreePath(root, ``, paths);
return paths;
}
My thought is that since in JS arrays are passed by reference, that I can pass the collecting array all the way down to the leaf nodes, at which point I can push strings into the array.
One large downside I see is that the recursive function isnāt a pure function, which I do prefer to write. But it seems like passing the reference is very efficient.
I also feel like constructing a string is more efficient than dealing with an array.
I would really like some feedback - Iām not trying to say that my method is best.
My answer is simpler, but it requires that there are no āNoneā values in the nodeās children list, which suits all the test cases.
def ternary_tree_paths(root: Node) -> List[str]:
def dfs(node, paths, cur_path):
if not node.children:
paths.append('->'.join(cur_path))
return
if not cur_path:
cur_path.append(str(node.val))
for child in node.children:
cur_path.append(str(child.val))
dfs(child, paths, cur_path)
cur_path.pop()
paths = []
dfs(root, paths, [])
return paths
Your way keeps reconstructing the strings over and over again which increases the time complexity
The solution with a global variable:
class Solution {
...
private static final List<String> TREE_PATHS = new ArrayList<>();
public static List<String> ternaryTreePaths(Node<Integer> root) {
if (root == null) return TREE_PATHS;
dfs(root, "");
return TREE_PATHS;
}
private static void dfs(Node<Integer> root, String path) {
path += root.val;
if (root.children.isEmpty()) {
TREE_PATHS.add(path);
} else {
for (Node<Integer> child : root.children) {
dfs(child, path + "->");
}
}
}
}
Here is my C++ solution. I think its a little easier to understand
void dfs(Node<int>* root, std::vector<std::string>& res, std::string path = "") {
if(root->children.empty()){
res.push_back(path + std::to_string(root->val));
return;
}
path.append(std::to_string(root->val) + "->");
for(Node<int>* child : root->children) {
dfs(child, res, path);
}
}
std::vector<std::string> ternary_tree_paths(Node<int>* root) {
if(root == nullptr) return {};
std::vector<std::string> result;
dfs(root, result);
return result;
}
let me know if you see any issues with it
The solution provided is hard to read, here is an alternate:
def ternary_tree_paths(root: Node) -> List[str]:
def helper(root, path, res):
if root is None:
return
current_path = path + [str(root.val)]
if not root.children:
res.append('->'.join(current_path))
else:
for child in root.children:
helper(child, current_path, res)
return res
result = helper(root,[],[])
return result
Here is my simplified solution
function ternaryTreePaths(root) {
function dfs(node, currPath, paths) {
if(!node.children || (node.children.length == 0)) {
paths.push(currPath.join("->"));
return;
}
node.children.forEach((child) => {
currPath.push(child.val);
dfs(child, currPath, paths);
currPath.pop();
});
}
let paths = [];
let currPath = [root.val];
dfs(root, currPath, paths);
return paths;
}