welcome to my blog
剑指offer面试题37(java版):序列化二叉树
题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
第四次做; 核心: 1) 二叉树的遍历 2)保留结构信息: 左右孩子, 空节点 3)分隔符 4)使用StringBuilder, 别使用String, 避免在字符串常量池中创建大量的无用字符串
public class Codec {
// Encodes a tree to a single string.
//递归; 二叉树的遍历, 采用前序遍历, 1)要保留结构信息(除了左右孩子, 还要考虑null), 2)要设置间隔符, 从而区分不同的val
public String serialize(TreeNode root) {
//base case
if(root==null)
return "#!";
StringBuilder sb = new StringBuilder();
sb.append(root.val).append("!");
sb.append(serialize(root.left));
sb.append(serialize(root.right));
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] strs = data.split("!");
return core(strs);
}
private int i;
//二叉树的遍历, 前序遍历, 递归
private TreeNode core(String[] strs){
//base case
if(i==strs.length)
return null;
if(strs[i].equals("#")){
i++; //索引++
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(strs[i]));
i++;
root.left = core(strs);
root.right = core(strs);
return root;
}
}
笔记
- java基础得牢固才行啊…
- String.valueOf(“15”)
- Integer.parseInt(“15”)
- str.split("")
思路
- 要对递归有感觉
- 使用了一个全局变量作为字符串数组的索引, 索引值在每次递归中改变
- 序列化和反序列化都使用了递归函数
- 我最开始犯错了, 把根节点的创建放在了函数外面, 结果导致逻辑混乱, 要把操作放在函数内部
第三次做; 结构信息的保存, 具体就是保存空节点; 需要一个全局索引; 反序列化中的while不需要越界检查, 因为序列化过程中数字的后面一定有个叹号
/*
结构信息的保存, 体现在空节点的处理上: 一定要以某种形式保存空节点!
*/
public class Solution {
String Serialize(TreeNode root) {
if(root==null)
return "#";
//前序: 根左右
return root.val+"!" + Serialize(root.left) + Serialize(root.right);
}
int index = 0;
TreeNode Deserialize(String str) {
if(str==null || index==str.length())
return null;
if(str.charAt(index)=='#'){
index++;
return null;
}
int i;
String curr="";
//这个while不用加越界判断index<str.length(); 因为序列化的过程一定在数字后面有个!
while(str.charAt(index)!='!'){
curr += str.charAt(index);
index++;
}
//跳到!下一个位置
index++;
TreeNode root = new TreeNode(Integer.valueOf(curr));
root.left = Deserialize(str);
root.right = Deserialize(str);
return root;
}
}
第二次做, 认真体会递归
public class Solution {
String Serialize(TreeNode root) {
if(root==null)
return "#";
//这一句包括对当前参数的处理, 以及更新参数后重新调用递归函数; (要时刻保持清醒:传入的参数和更新后的参数的处理流程都是一样的)
return root.val+"!"+Serialize(root.left)+Serialize(root.right);
}
int index = 0;
TreeNode Deserialize(String str) {
if(index == str.length())
return null;
if(str.charAt(index) == '#'){
index++;
return null;
}
String curr = "";
while(str.charAt(index) != '!'){
curr = curr + str.charAt(index);
index++;
}
TreeNode node = new TreeNode(Integer.valueOf(curr));
//跳过叹号
index++;
node.left = Deserialize(str);
node.right = Deserialize(str);
return node;
}
}
public class Solution {
public String Serialize(TreeNode root) {
//input check
if(root == null)
return "";
StringBuffer sb = new StringBuffer();
SerializeCore(root, sb);
return sb.toString();
}
public void SerializeCore(TreeNode root, StringBuffer sb){
//递归函数功能: 将当前节点的值存在String中
if(root == null){
sb.append("#,");
}
else{
//根左右
sb.append(String.valueOf(root.val)+','); // StringBuffer会自动将int转成字符串
SerializeCore(root.left, sb);
SerializeCore(root.right, sb);
}
}
/
/
public TreeNode Deserialize(String str) {
// input check
if(str.length() < 1 )
return null;
//execute
String[] s = str.split(",");
TreeNode root = new TreeNode(Integer.parseInt(s[0]));
return DeserializeCore(s);
}
public int index = 0;
public TreeNode DeserializeCore(String[] str){
TreeNode root = null;
if(index < str.length && str[index].equals("#")){
index++;
return null;
}
else{ //递归终止条件: index = str.length
// 在函数内部创建节点, 执行完函数还存在吗? 被外部变量使用的话可能就不会被销毁了, 所以参数中还需要一个指针
root = new TreeNode(Integer.parseInt(str[index++]) );
root.left = DeserializeCore(str);
root.right = DeserializeCore(str);
}
return root;
}
}
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
精简一些的答案
public class Solution {
public int index = -1;
String Serialize(TreeNode root) {
StringBuffer sb = new StringBuffer();
if(root == null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val + ",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
index++;
int len = str.length();
if(index >= len){
return null;
}
String[] strr = str.split(",");
TreeNode node = null;
if(!strr[index].equals("#")){
node = new TreeNode(Integer.valueOf(strr[index]));
node.left = Deserialize(str);
node.right = Deserialize(str);
}
return node;
}
}