[LC] 428. Serialize and Deserialize N-ary Tree

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才能最后调出结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值