From 7c40236b69249674a94392cbc58f8f34b8a9e343 Mon Sep 17 00:00:00 2001 From: AC_Oier Date: Wed, 30 Jun 2021 11:32:48 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20Add=20=E5=89=91=E6=8C=87=20Off?= =?UTF-8?q?er=2037=E3=80=81297?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Index/BFS.md | 1 + .../\344\272\214\345\217\211\346\240\221.md" | 8 ++ ...10\345\233\260\351\232\276\357\274\211.md" | 129 ++++++++++++++++++ ...10\345\233\260\351\232\276\357\274\211.md" | 129 ++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 "Index/\344\272\214\345\217\211\346\240\221.md" create mode 100644 "LeetCode/291-300/297. \344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226\357\274\210\345\233\260\351\232\276\357\274\211.md" create mode 100644 "LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 37. \345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221\357\274\210\345\233\260\351\232\276\357\274\211.md" diff --git a/Index/BFS.md b/Index/BFS.md index d32932be..82306b96 100644 --- a/Index/BFS.md +++ b/Index/BFS.md @@ -1,6 +1,7 @@ | 题目 | 题解 | 难度 | 推荐指数 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- | | [90. 子集 II](https://leetcode-cn.com/problems/subsets-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/subsets-ii/solution/gong-shui-san-xie-yi-ti-shuang-jie-hui-s-g77q/) | 中等 | 🤩🤩🤩🤩 | +| [297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/) | 困难 | | | [403. 青蛙过河](https://leetcode-cn.com/problems/frog-jump/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/frog-jump/solution/gong-shui-san-xie-yi-ti-duo-jie-jiang-di-74fw/) | 困难 | 🤩🤩🤩🤩 | | [690. 员工的重要性](https://leetcode-cn.com/problems/employee-importance/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/employee-importance/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-s79x/) | 简单 | 🤩🤩🤩 | | [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 | diff --git "a/Index/\344\272\214\345\217\211\346\240\221.md" "b/Index/\344\272\214\345\217\211\346\240\221.md" new file mode 100644 index 00000000..22ecf71b --- /dev/null +++ "b/Index/\344\272\214\345\217\211\346\240\221.md" @@ -0,0 +1,8 @@ +| 题目 | 题解 | 难度 | 推荐指数 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- | +| [297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/) | 困难 | 🤩🤩🤩🤩🤩 | +| [783. 二叉搜索树节点最小距离](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/solution/gong-shui-san-xie-yi-ti-san-jie-shu-de-s-7r17/) | 简单 | 🤩🤩🤩 | +| [938. 二叉搜索树的范围和](https://leetcode-cn.com/problems/range-sum-of-bst/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/range-sum-of-bst/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-q2fo/) | 简单 | 🤩🤩🤩 | +| [993. 二叉树的堂兄弟节点](https://leetcode-cn.com/problems/cousins-in-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/cousins-in-binary-tree/solution/gong-shui-san-xie-shu-de-sou-suo-dfs-bfs-b200/) | 简单 | 🤩🤩 | +| [剑指 Offer 37. 序列化二叉树](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/) | 困难 | 🤩🤩🤩🤩🤩 | + diff --git "a/LeetCode/291-300/297. \344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226\357\274\210\345\233\260\351\232\276\357\274\211.md" "b/LeetCode/291-300/297. \344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226\357\274\210\345\233\260\351\232\276\357\274\211.md" new file mode 100644 index 00000000..26705ea0 --- /dev/null +++ "b/LeetCode/291-300/297. \344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\344\270\216\345\217\215\345\272\217\345\210\227\345\214\226\357\274\210\345\233\260\351\232\276\357\274\211.md" @@ -0,0 +1,129 @@ +### 题目描述 + +这是 LeetCode 上的 **[297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/)** ,难度为 **困难**。 + +Tag : 「二叉树」、「层序遍历」 + + + +序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 + +请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。 + +提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。 + +示例 1: +![](https://assets.leetcode.com/uploads/2020/09/15/serdeser.jpg) +``` +输入:root = [1,2,3,null,null,4,5] +输出:[1,2,3,null,null,4,5] +``` +示例 2: +``` +输入:root = [] +输出:[] +``` +示例 3: +``` +输入:root = [1] +输出:[1] +``` +示例 4: +``` +输入:root = [1,2] +输出:[1,2] +``` + +提示: +* 树中结点数在范围 $[0, 10^4]$ 内 +* -1000 <= Node.val <= 1000 + +--- + +### 基本思路 + +无论使用何种「遍历方式」进行二叉树存储,为了方便,我们都需要对空节点有所表示。 + +其实题目本身的样例就给我们提供了很好的思路:**使用层序遍历的方式进行存储,对于某个叶子节点的空节点进行存储,同时确保不递归存储空节点对应的子节点。** + +--- + +### 层序遍历 + +根据节点值的数据范围 `-1000 <= Node.val <= 1000`(我是在 [297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) 看的,你也可以不使用数字,使用某个特殊字符进行表示,只要能在反序列时有所区分即可),我们可以建立占位节点 `emptyNode` 用来代指空节点(`emptyNode.val = INF`)。 + +序列化:先特判掉空树的情况,之后就是常规的层序遍历逻辑: + +1. 起始时,将 `root` 节点入队; +2. 从队列中取出节点,检查节点是否有左/右节点: + * 如果有的话,将值追加序列化字符中(注意使用分隔符),并将节点入队; + * 如果没有,检查当前节点是否为 `emptyNode` 节点,如果不是 `emptyNode` 说明是常规的叶子节点,需要将其对应的空节点进行存储,即将 `emptyNode` 入队; +3. 循环流程 $2$,直到整个队列为空。 + +反序列:同理,怎么「序列化」就怎么进行「反序列」即可: + +1. 起始时,构造出 `root` 并入队; +2. 每次从队列取出元素时,同时从序列化字符中截取两个值(对应左右节点),检查是否为 `INF`,若不为 `INF` 则构建对应节点; +3. 循环流程 $2$,直到整个序列化字符串被处理完(注意跳过最后一位分隔符)。 + +代码: +```Java [] +public class Codec { + int INF = -2000; + TreeNode emptyNode = new TreeNode(INF); + public String serialize(TreeNode root) { + if (root == null) return ""; + + StringBuilder sb = new StringBuilder(); + Deque d = new ArrayDeque<>(); + d.addLast(root); + while (!d.isEmpty()) { + TreeNode poll = d.pollFirst(); + sb.append(poll.val + "_"); + if (!poll.equals(emptyNode)) { + d.addLast(poll.left != null ? poll.left : emptyNode); + d.addLast(poll.right != null ? poll.right : emptyNode); + } + } + return sb.toString(); + } + + public TreeNode deserialize(String data) { + if (data.equals("")) return null; + + String[] ss = data.split("_"); + int n = ss.length; + TreeNode root = new TreeNode(Integer.parseInt(ss[0])); + Deque d = new ArrayDeque<>(); + d.addLast(root); + for (int i = 1; i < n - 1; i += 2) { + TreeNode poll = d.pollFirst(); + int a = Integer.parseInt(ss[i]), b = Integer.parseInt(ss[i + 1]); + if (a != INF) { + poll.left = new TreeNode(a); + d.addLast(poll.left); + } + if (b != INF) { + poll.right = new TreeNode(b); + d.addLast(poll.right); + } + } + return root; + } +} +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(n)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.297` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 37. \345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221\357\274\210\345\233\260\351\232\276\357\274\211.md" "b/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 37. \345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221\357\274\210\345\233\260\351\232\276\357\274\211.md" new file mode 100644 index 00000000..603620b0 --- /dev/null +++ "b/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 37. \345\272\217\345\210\227\345\214\226\344\272\214\345\217\211\346\240\221\357\274\210\345\233\260\351\232\276\357\274\211.md" @@ -0,0 +1,129 @@ +### 题目描述 + +这是 LeetCode 上的 **[剑指 Offer 37. 序列化二叉树](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/)** ,难度为 **困难**。 + +Tag : 「二叉树」、「层序遍历」 + + + +序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 + +请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。 + +提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。 + +示例 1: +![](https://assets.leetcode.com/uploads/2020/09/15/serdeser.jpg) +``` +输入:root = [1,2,3,null,null,4,5] +输出:[1,2,3,null,null,4,5] +``` +示例 2: +``` +输入:root = [] +输出:[] +``` +示例 3: +``` +输入:root = [1] +输出:[1] +``` +示例 4: +``` +输入:root = [1,2] +输出:[1,2] +``` + +提示: +* 树中结点数在范围 $[0, 10^4]$ 内 +* -1000 <= Node.val <= 1000 + +--- + +### 基本思路 + +无论使用何种「遍历方式」进行二叉树存储,为了方便,我们都需要对空节点有所表示。 + +其实题目本身的样例就给我们提供了很好的思路:**使用层序遍历的方式进行存储,对于某个叶子节点的空节点进行存储,同时确保不递归存储空节点对应的子节点。** + +--- + +### 层序遍历 + +根据节点值的数据范围 `-1000 <= Node.val <= 1000`(我是在 [297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) 看的,你也可以不使用数字,使用某个特殊字符进行表示,只要能在反序列时有所区分即可),我们可以建立占位节点 `emptyNode` 用来代指空节点(`emptyNode.val = INF`)。 + +序列化:先特判掉空树的情况,之后就是常规的层序遍历逻辑: + +1. 起始时,将 `root` 节点入队; +2. 从队列中取出节点,检查节点是否有左/右节点: + * 如果有的话,将值追加序列化字符中(注意使用分隔符),并将节点入队; + * 如果没有,检查当前节点是否为 `emptyNode` 节点,如果不是 `emptyNode` 说明是常规的叶子节点,需要将其对应的空节点进行存储,即将 `emptyNode` 入队; +3. 循环流程 $2$,直到整个队列为空。 + +反序列:同理,怎么「序列化」就怎么进行「反序列」即可: + +1. 起始时,构造出 `root` 并入队; +2. 每次从队列取出元素时,同时从序列化字符中截取两个值(对应左右节点),检查是否为 `INF`,若不为 `INF` 则构建对应节点; +3. 循环流程 $2$,直到整个序列化字符串被处理完(注意跳过最后一位分隔符)。 + +代码: +```Java [] +public class Codec { + int INF = -2000; + TreeNode emptyNode = new TreeNode(INF); + public String serialize(TreeNode root) { + if (root == null) return ""; + + StringBuilder sb = new StringBuilder(); + Deque d = new ArrayDeque<>(); + d.addLast(root); + while (!d.isEmpty()) { + TreeNode poll = d.pollFirst(); + sb.append(poll.val + "_"); + if (!poll.equals(emptyNode)) { + d.addLast(poll.left != null ? poll.left : emptyNode); + d.addLast(poll.right != null ? poll.right : emptyNode); + } + } + return sb.toString(); + } + + public TreeNode deserialize(String data) { + if (data.equals("")) return null; + + String[] ss = data.split("_"); + int n = ss.length; + TreeNode root = new TreeNode(Integer.parseInt(ss[0])); + Deque d = new ArrayDeque<>(); + d.addLast(root); + for (int i = 1; i < n - 1; i += 2) { + TreeNode poll = d.pollFirst(); + int a = Integer.parseInt(ss[i]), b = Integer.parseInt(ss[i + 1]); + if (a != INF) { + poll.left = new TreeNode(a); + d.addLast(poll.left); + } + if (b != INF) { + poll.right = new TreeNode(b); + d.addLast(poll.right); + } + } + return root; + } +} +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(n)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `剑指 Offer 37` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 +