https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree/
实话说在我心目中leetcode里面的题目,有些hard是属于需要很巧妙的解法,有些hard是属于很烦但是不太涉及很巧妙的算法。这一题就属于很麻烦的那一种。
其实这样的serialize和deserialize核心算法还是bfs或者dfs,题目的描述里其实提示已经很明显了。第一种表达方式就是dfs的解法,而第二种的表达方式显然就是bfs的解法。
我们这里就基本跟从第一种表达方式来做,细节上稍微有点差别。
serialize:
1.遇到一个节点,就先把数值加到里面。
2.如果这个节点存在children,那么后面就append一个左括号[,接着dfs进入每个节点的下一层(回到1)。在dfs自下而上返回时,后面加一个空格。这个空格可能会被改写成右括号,如果我们遍历完了所有的children节点。
譬如说题目描述里的第一棵树,它serialize之后的字符串会是 1[3[5 6] 2 4],和它自己展示出来的稍微不同。
第二棵树,便会是1[2 3[6 7[11[14]] 4[8[12]] 5[9[13] 10]]]
deserialize其实思路不复杂,但是要处理的case有点麻烦
保留一个全局的index作为遍历用的cursor
1. 字符遍历出一个数字(需要考虑到当前cursor停留在一个空格上,这个会因为从某一个右括号脱出后导致)。
2. 看看数字之后的是啥
2a. 如果是左括号,就表示存在children,cursor前进一格到数字那里,进入下一层的children遍历。遍历结束点为下一层dfs返回时,当前cursor停留在一个右括号上。
2b. 如果是空格, 就表示这一层还有其他的children,cursor要再往前一个走到下一个数字的起始点
2c. 如果是右括号,就表示这一层结束了,cursor不动,留给上一层的dfs处理。(之所以要留给上一层的dfs是因为右括号是遍历的结束条件)
3. 如果是2a的情况,cursor需要往前再走一步,表示脱离了当前这个节点的children节点的处理。
4. 返回当前节点。
根据上面思路,可以得到代码如下:
public String serialize(Node root) {
if (root == null) return "";
StringBuilder strBlder = new StringBuilder();
dfsSerialize(root, strBlder);
return strBlder.toString();
}
public void dfsSerialize(Node curNode, StringBuilder strBlder) {
strBlder.append(curNode.val);
if (curNode.children != null && !curNode.children.isEmpty()) {
strBlder.append('[');
for (Node node : curNode.children) {
dfsSerialize(node, strBlder);
strBlder.append(' ');
}
strBlder.setCharAt(strBlder.length() - 1, ']');
}
}
// Decodes your encoded data to tree.
public Node deserialize(String data) {
if (data.equals("")) return null;
return dfsDeserialize(data, new int[]{0});
}
public Node dfsDeserialize(String data, int[] idx) {
if (data.charAt(idx[0]) == ' ') idx[0]++;
int val = 0;
while (idx[0] < data.length() && data.charAt(idx[0]) >= '0' && data.charAt(idx[0]) <= '9') {
val = val * 10 + (data.charAt(idx[0]) - '0');
idx[0]++;
}
Node node = new Node(val, new LinkedList<>());
if (idx[0] < data.length() && data.charAt(idx[0]) == '[') {
idx[0]++;
while (idx[0] < data.length() && data.charAt(idx[0]) != ']') {
node.children.add(dfsDeserialize(data, idx));
}
idx[0]++;
} else if(idx[0] < data.length() && data.charAt(idx[0]) != ']') {
idx[0]++;
}
return node;
}
这个真的是烦,烦到我做第二次的时候还是需要依赖debug才能最后调出结果。