diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/memo.md b/0297.Serialize-and-Deserialize-Binary-Tree/memo.md new file mode 100644 index 0000000..79e6087 --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/memo.md @@ -0,0 +1,70 @@ +# 297. Serialize and Deserialize Binary Tree + +## step1 + +37mぐらいかかった。確実に解けると思ったが、スラスラと書くことができなかった。 + +幅優先探索で解くことにした。 + +間違えた点: +- delimをつけずに間違えた(数字が2桁だとdecodeできない) +- deserializeでキューになぜかNoneを入れた + + +## step2 + +https://support.leetcode.com/hc/en-us/articles/32442719377939-How-to-create-test-cases-on-LeetCode#h_01J5EGREAW3NAEJ14XC07GRW1A + +こんなサイトがあることを知らなかった。level order traversalという名前がついていたんだった。 + +探索順は同じだが、serializeした文字列がこちらの方が短い。nullの場合の処理が異なる。 + +この場合、自身をresultに入れてから、子をresultに入れるとかける: step2 + +こちらも書くのに20mぐらいかかった。 + +書きながら注意したことで、以下は正しく動かない。 + +```python +child = node.left +child = TreeNode(0) +``` + +これはPythonの変数がオブジェクトの参照であるためで、childが単に`TreeNode(0)`オブジェクトを指すようになる、という変更になる。 + +## 他の解法 + +LeetCodeの与えられ方に引きずられて、level-orderを最初に選択したが、DFSでも解くことができるはず。 + +11mぐらいでかけた。 + +Pre-orderとPost-orderは可能だが、In-orderは可能なのか?おそらく不可能だと思う。理由は、in-orderだとnull Nodeがある場合に根の位置が特定できないから。 + + +LeetCodeのSolutionを検索すると in-order と書かれているものがあったが、コードを読むと実際にはpre-orderであった。 +https://leetcode.com/problems/serialize-and-deserialize-binary-tree/solutions/6678162/in-order-traversal-simple-solution-by-th-822j/?envType=problem-list-v2&envId=rab78cw1 + + + +## 他の人のコード + +https://github.com/hayashi-ay/leetcode/pull/74 + +> 書いてみた感想として、探索だけならDFSもBFSもそこまで書きやすさは変わらないですが、Treeの構築が発生する場合はBFSおよびDFSのループだと書きにくいなと思いました。親ノードや左右どちらにつなぐかなどを考えないといけないので。 + +確かに自分もBFSで書くので苦戦し、再帰DFSで書くと簡単にかけた + +自分はindexを使ったが、iteratorを使っている。例外で処理しようとしたが、nextの引数defaultを勧められている。nextの引数defaultは知らなかった。 + +https://docs.python.org/3/library/functions.html#next + +https://github.com/shining-ai/leetcode/pull/62 + +> イテレータを使う発想がありませんでした。 + +自分も同じく。 + +https://github.com/potrue/leetcode/pull/73 + +## step3 +最も個人的に自然な pre-orderを書いておく diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/step1_level_order.py b/0297.Serialize-and-Deserialize-Binary-Tree/step1_level_order.py new file mode 100644 index 0000000..503be73 --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/step1_level_order.py @@ -0,0 +1,77 @@ +import collections + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + NO_NODE = "n" + DELIM = "," + + def serialize(self, root: TreeNode | None) -> str: + """Encodes a tree to a single string.""" + if root is None: + return self.NO_NODE + + frontier = collections.deque([root]) + result = [] + + while frontier: + node = frontier.popleft() + if node is None: + result.append(self.NO_NODE) + continue + + result.append(str(node.val)) + frontier.append(node.left) + frontier.append(node.right) + + return self.DELIM.join(result) + + def _create_node(self, c: str) -> TreeNode | None: + if c == self.NO_NODE: + return None + return TreeNode(int(c)) + + def deserialize(self, data: str) -> TreeNode | None: + """Decodes your encoded data to tree.""" + if not data or data == self.NO_NODE: + return None + + tokens = data.split(self.DELIM) + + root = self._create_node(tokens[0]) + frontier = collections.deque([root]) + + i = 1 + while i < len(tokens): + node = frontier.popleft() + + if node is None: + continue + + node.left = self._create_node(tokens[i]) + if node.left: + frontier.append(node.left) + i += 1 + + if i >= len(tokens): + continue + + node.right = self._create_node(tokens[i]) + if node.right: + frontier.append(node.right) + i += 1 + + return root + + +# Your Codec object will be instantiated and called as such: +# ser = Codec() +# deser = Codec() +# ans = deser.deserialize(ser.serialize(root)) diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/step2_level_order_short.py b/0297.Serialize-and-Deserialize-Binary-Tree/step2_level_order_short.py new file mode 100644 index 0000000..d5cdcaf --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/step2_level_order_short.py @@ -0,0 +1,61 @@ +import collections + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + NO_NODE = "n" + DELIM = "," + + def serialize(self, root: TreeNode | None) -> str: + """Encodes a tree to a single string.""" + if root is None: + return self.NO_NODE + + result = [str(root.val)] + frontier = collections.deque([root]) + + while frontier: + node = frontier.popleft() + for child in (node.left, node.right): + if child is not None: + result.append(str(child.val)) + frontier.append(child) + else: + result.append(self.NO_NODE) + + while result and result[-1] == self.DELIM: + result.pop() + + return self.DELIM.join(result) + + def deserialize(self, data: str) -> TreeNode | None: + """Decodes your encoded data to tree.""" + if not data or data == self.NO_NODE: + return None + + tokens = data.split(self.DELIM) + + root = TreeNode(tokens[0]) + frontier = collections.deque([root]) + + i = 1 + while i < len(tokens): + node = frontier.popleft() + + for child_name in ("left", "right"): + if tokens[i] != self.NO_NODE: + child = TreeNode(tokens[i]) + setattr(node, child_name, child) + frontier.append(child) + i += 1 + if i >= len(tokens): + break + + return root diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/step2_postorder.py b/0297.Serialize-and-Deserialize-Binary-Tree/step2_postorder.py new file mode 100644 index 0000000..29b6c24 --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/step2_postorder.py @@ -0,0 +1,50 @@ +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + NO_NODE = "n" + DELIM = "," + + def serialize(self, root: TreeNode | None) -> str: + """Encodes a tree to a single string.""" + result = [] + + def traverse(node): + if node is None: + result.append(self.NO_NODE) + return + + traverse(node.left) + traverse(node.right) + result.append(str(node.val)) + + traverse(root) + return self.DELIM.join(result) + + def deserialize(self, data: str) -> TreeNode | None: + """Decodes your encoded data to tree.""" + if not data or data == self.NO_NODE: + return None + + tokens = data.split(self.DELIM) + + def traverse() -> TreeNode | None: + if not tokens: + return None + + token = tokens.pop() + if token == self.NO_NODE: + return None + + node = TreeNode(token) + node.right = traverse() + node.left = traverse() + + return node + + return traverse() diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/step2_preorder.py b/0297.Serialize-and-Deserialize-Binary-Tree/step2_preorder.py new file mode 100644 index 0000000..dcda725 --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/step2_preorder.py @@ -0,0 +1,55 @@ +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + NO_NODE = "n" + DELIM = "," + + def serialize(self, root: TreeNode | None) -> str: + """Encodes a tree to a single string.""" + result = [] + + def traverse(node): + if node is None: + result.append(self.NO_NODE) + return + + result.append(str(node.val)) + traverse(node.left) + traverse(node.right) + + traverse(root) + return self.DELIM.join(result) + + def deserialize(self, data: str) -> TreeNode | None: + """Decodes your encoded data to tree.""" + if not data or data == self.NO_NODE: + return None + + tokens = data.split(self.DELIM) + + i = 0 + + def traverse(): + nonlocal i + + if i >= len(tokens): + return None + + if tokens[i] == self.NO_NODE: + i += 1 + return + + node = TreeNode(tokens[i]) + i += 1 + node.left = traverse() + node.right = traverse() + + return node + + return traverse() diff --git a/0297.Serialize-and-Deserialize-Binary-Tree/step3_preorder.py b/0297.Serialize-and-Deserialize-Binary-Tree/step3_preorder.py new file mode 100644 index 0000000..ddd4dde --- /dev/null +++ b/0297.Serialize-and-Deserialize-Binary-Tree/step3_preorder.py @@ -0,0 +1,50 @@ +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Codec: + NO_NODE = "n" + DELIM = "," + + def serialize(self, root: TreeNode | None) -> str: + """Encodes a tree to a single string.""" + result = [] + + def traverse(node): + if node is None: + result.append(self.NO_NODE) + return + result.append(str(node.val)) + traverse(node.left) + traverse(node.right) + + traverse(root) + while result and result[-1] == self.NO_NODE: + result.pop() + + return self.DELIM.join(result) + + def deserialize(self, data: str) -> TreeNode | None: + """Decodes your encoded data to tree.""" + if not data or data == self.NO_NODE: + return None + + tokens = data.split(self.DELIM) + token_iterator = iter(tokens) + + def traverse(): + token = next(token_iterator, None) + if token is None or token == self.NO_NODE: + return None + + node = TreeNode(int(token)) + node.left = traverse() + node.right = traverse() + + return node + + return traverse()