It's easy to find if you know what you're looking for.
node
若是你知道本身想追求什麼,就很容易成功。web
問題描述算法
序列化是將一個數據結構或者對象轉換爲連續的比特位的操做,進而能夠將轉換後的數據存儲在一個文件或者內存中,同時也能夠經過網絡傳輸到另外一個計算機環境,採起相反方式重構獲得原數據。微信
請設計一個算法來實現二叉樹的序列化與反序列化。這裏不限定你的序列 / 反序列化算法執行邏輯,你只須要保證一個二叉樹能夠被序列化爲一個字符串而且將這個字符串反序列化爲原始的樹結構。網絡
示例: 數據結構
你能夠將如下二叉樹:app
1數據結構和算法
/ \編輯器
2 3svg
/ \
4 5
序列化爲 "[1,2,3,null,null,4,5]"
BFS解決
這題上面說了一大堆,其實就是把二叉樹轉化爲一個字符串,而且還能把這個字符串還原成原來的二叉樹就能夠了。
把二叉樹轉化爲字符串能夠有不少種方式,好比前序遍歷,中序遍歷,後續遍歷,BFS,DFS都是能夠的,對於樹的各類遍歷具體能夠看下373,數據結構-6,樹。但這題還要求把字符串再還原成原來的二叉樹。最容易想到的就是BFS,就是一層一層從往下遍歷
來看下代碼
1public class Codec {
2
3 //把樹轉化爲字符串(使用BFS遍歷)
4 public String serialize(TreeNode root) {
5 //邊界判斷,若是爲空就返回一個字符串"#"
6 if (root == null)
7 return "#";
8 //建立一個隊列
9 Queue<TreeNode> queue = new LinkedList<>();
10 StringBuilder res = new StringBuilder();
11 //把根節點加入到隊列中
12 queue.add(root);
13 while (!queue.isEmpty()) {
14 //節點出隊
15 TreeNode node = queue.poll();
16 //若是節點爲空,添加一個字符"#"做爲空的節點
17 if (node == null) {
18 res.append("#,");
19 continue;
20 }
21 //若是節點不爲空,把當前節點的值加入到字符串中,
22 //注意節點之間都是以逗號","分隔的,在下面把字符
23 //串還原二叉樹的時候也是以逗號","把字符串進行拆分
24 res.append(node.val + ",");
25 //左子節點加入到隊列中(左子節點有可能爲空)
26 queue.add(node.left);
27 //右子節點加入到隊列中(右子節點有可能爲空)
28 queue.add(node.right);
29 }
30 return res.toString();
31 }
32
33 //把字符串還原爲二叉樹
34 public TreeNode deserialize(String data) {
35 //若是是"#",就表示一個空的節點
36 if (data == "#")
37 return null;
38 Queue<TreeNode> queue = new LinkedList<>();
39 //由於上面每一個節點之間是以逗號","分隔的,因此這裏
40 //也要以逗號","來進行拆分
41 String[] values = data.split(",");
42 //上面使用的是BFS,因此第一個值就是根節點的值,這裏建立根節點
43 TreeNode root = new TreeNode(Integer.parseInt(values[0]));
44 queue.add(root);
45 for (int i = 1; i < values.length; i++) {
46 //隊列中節點出棧
47 TreeNode parent = queue.poll();
48 //由於在BFS中左右子節點是成對出現的,因此這裏挨着的兩個值一個是
49 //左子節點的值一個是右子節點的值,當前值若是是"#"就表示這個子節點
50 //是空的,若是不是"#"就表示不是空的
51 if (!"#".equals(values[i])) {
52 TreeNode left = new TreeNode(Integer.parseInt(values[i]));
53 parent.left = left;
54 queue.add(left);
55 }
56 //上面若是不爲空就是左子節點的值,這裏是右子節點的值,注意這裏有個i++,
57 if (!"#".equals(values[++i])) {
58 TreeNode right = new TreeNode(Integer.parseInt(values[i]));
59 parent.right = right;
60 queue.add(right);
61 }
62 }
63 return root;
64 }
65}
DFS解決
DFS遍歷是從根節點開始,一直往左子節點走,當到達葉子節點的時候會返回到父節點,而後從從父節點的右子節點繼續遍歷……
1class Codec {
2
3 //把樹轉化爲字符串(使用DFS遍歷,也是前序遍歷,順序是:根節點→左子樹→右子樹)
4 public String serialize(TreeNode root) {
5 //邊界判斷,若是爲空就返回一個字符串"#"
6 if (root == null)
7 return "#";
8 return root.val + "," + serialize(root.left) + "," + serialize(root.right);
9 }
10
11 //把字符串還原爲二叉樹
12 public TreeNode deserialize(String data) {
13 //把字符串data以逗號","拆分,拆分以後存儲到隊列中
14 Queue<String> queue = new LinkedList<>(Arrays.asList(data.split(",")));
15 return helper(queue);
16 }
17
18 private TreeNode helper(Queue<String> queue) {
19 //出隊
20 String sVal = queue.poll();
21 //若是是"#"表示空節點
22 if ("#".equals(sVal))
23 return null;
24 //不然建立當前節點
25 TreeNode root = new TreeNode(Integer.valueOf(sVal));
26 //分別建立左子樹和右子樹
27 root.left = helper(queue);
28 root.right = helper(queue);
29 return root;
30 }
31}
總結
把二叉樹轉化爲字符串很簡單,關鍵是怎麼把轉化的字符串再還原成原來的二叉樹,這裏使用BFS和DFS都很容易實現。
長按上圖,識別圖中二維碼以後便可關注。
若是以爲有用就點個"贊"吧
本文分享自微信公衆號 - 數據結構和算法(sjjghsf)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。