• 力扣297题(序列化二叉树,反序列化二叉树,递归)


    https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/shou-hui-tu-jie-gei-chu-dfshe-bfsliang-chong-jie-f/

    抄的力扣一位大佬的

    前序遍历解法 DFS

    基本思想:

    (1)序列化:

    遍历将各个节点的值放到一个列表中

    将列表用join()再变成字符串

    (2)反序列化:

    确定根节点root,然后遵循前序遍历的结果,递归生成左右子树

    具体实现:

    几个内置函数

    (1)join()

    str = "-";
    seq = ("a", "b", "c"); # 字符串序列
    print str.join( seq );

    a-b-c

    (2)next()

    next(迭代器)

    每执行一次,返回迭代器中的下一个项目

    只有迭代器才能用next()

    (3)iter()

    将可迭代对象变成迭代器

    https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640

    (4)split()

    按规定字符将字符串分割开

    string = "www.gziscas.com.cn"
    
    print(string.split('.'))
    
    ['www', 'gziscas', 'com', 'cn']

    代码:

    def serialize(self, root):
            """Encodes a tree to a single string.
    
            :type root: TreeNode
            :rtype: str
            """
    
            def dfs(node):
                if node:
                    vals.append(str(node.val))
                    dfs(node.left)
                    dfs(node.right)
                else:
                    vals.append("#")
    
            vals = []
            dfs(root)
            return ",".join(vals)
    
        def deserialize(self, data):
            """Decodes your encoded data to tree.
            :type data: str
            :rtype: TreeNode
            """
    
            def dfs():
                v = next(vals)
                if v == "#":
                    return None
                node = TreeNode(int(v))
                node.left = dfs()
                node.right = dfs()
                return node
            vals = iter(data.split(","))
            return dfs()

    基本思想:

    DFS

    前序遍历

    具体实现:

    序列化:

     递归三步:

    1、递归参数以及返回结果

    参数:根节点

    返回结果:以这个节点为根节点的序列化·

    2、递归终止条件

    递归到null节点返回

    3、单层递归逻辑

    递归遍历一棵树,重点关注当前节点,他的自述的遍历交给递归完成

    “serialize函数,请帮我分别序列化我的左右子树,我等你返回的结果,再拼接一下。”

    反序列化:

    递归三步:

    1、确定递归参数以及返回值

    递归参数:二叉树序列化后的字符串

    返回值:当前构建好的root

    2、递归终止条件

    遍历到‘x’时,代表碰到了空节点,返回null

    3、单层递归逻辑

    定义函数 buildTree 用于还原二叉树,传入由序列化字符串转成的 list 数组。
    逐个 pop 出 list 的首项,构建当前子树的根节点,顺着 list,构建顺序是根节点,左子树,右子树。
    如果弹出的字符为 "X",则返回 null 节点。
    如果弹出的字符是数值,则创建root节点,并递归构建root的左右子树,最后返回root。

    代码:

    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            if (root == null) return "X,";
            String leftSerialize = serialize(root.left); //左子树的序列化字符串
            String rightSerialize = serialize(root.right); //右子树的序列化字符串
            return root.val + "," + leftSerialize + rightSerialize;//能递归到的节点都当过根节点
        }
        /*
        public String serialize(TreeNode root) {
            if (root == null) return "X";
            String leftSerialize = serialize(root.left); //左子树的序列化字符串
            String rightSerialize = serialize(root.right); //右子树的序列化字符串
            return root.val + "," + leftSerialize +","+ rightSerialize;
        }
        */
    
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
                String[] temp = data.split(",");
                Deque<String> dp = new LinkedList<>(Arrays.asList(temp));
                return buildTree(dp);
            }
            private TreeNode buildTree(Deque<String> dq){
                String s = dq.poll(); //返回当前结点
                if (s.equals("X")) return null;
                TreeNode node = new TreeNode(Integer.parseInt(s));
                node.left = buildTree(dq); //构建左子树
                node.right = buildTree(dq); //构建右子树
                return node;
            }
    }

    层级遍历解法 BFS

    基本思想:

    先捋清楚啥是层级遍历就啥也好说了

    具体实现:

    序列化

    和DFS得到的不同,它是一层层的。除了第一个是根节点的值,其他节点值都是成对的,对应左右子节点。

    反序列化

    依然先转成list数组,用一个指针 cursor 从第二项开始扫描。
    起初,用list[0]构建根节点,并让根节点入列。
    节点出列,此时 cursor 指向它的左子节点值,cursor+1 指向它的右子节点值。
            如果子节点值是数值,则创建节点,并认出列的父亲,同时自己也是父亲,入列。
       如果子节点值为 'X',什么都不用做,因为出列的父亲的 left 和 right 本来就是 null
    可见,所有的真实节点都会在队列里走一遍,出列就带出儿子入列

    代码:

    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
             if (root == null) {
                return "";
            }
            StringBuilder sb = new StringBuilder();//创建一个放结果的字符串
            Queue<TreeNode> queue = new LinkedList<>();//创建一个队列
            queue.offer(root);//放入待考察的节点
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll(); //考察出列的节点
                if (node == null) {//不是真实节点
                    sb.append("X,");
                } 
                else {//是真实节点
                    sb.append(node.val + ","); //节点值加入sb
                    queue.offer(node.left);//子节点入列,不管是不是null节点都入列
                    queue.offer(node.right);
                }
            }
            return sb.toString(); 
        }
        
    
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            if (data == "") {
                return null;
            }
            //序列化字符串给转为成数组
            Queue<String> nodes = new ArrayDeque<>(Arrays.asList(data.split(",")));
            //获取首项,构建根节点
            TreeNode root = new TreeNode(Integer.parseInt(nodes.poll()));
            //创建一个队列
            Queue<TreeNode> queue = new ArrayDeque<>();
            //根节点推入队列
            queue.offer(root);
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll(); //考察出列的节点
                String left = nodes.poll(); // 左儿子
                String right = nodes.poll(); // 右儿子
                if (!left.equals("X")) { // 是真实节点
                    node.left = new TreeNode(Integer.parseInt(left)); // 创建左儿子节点,然后认父亲
                    queue.add(node.left); //左儿子自己也是父亲,入列
                }
                if (!right.equals("X")) { 
                    node.right = new TreeNode(Integer.parseInt(right));
                    queue.add(node.right);
                }
            }
            return root;
        }
    }
  • 相关阅读:
    伍佰《突然的自我》
    .NET常见ORM框架
    并发和压测工具
    底层源码调试工具
    c 冒泡排序
    c 指定范围的质数
    c 筛法列举质数
    c 牛顿法求方程近似解
    c 二分法求方程近似解
    css选择器 及其权重
  • 原文地址:https://www.cnblogs.com/zhaojiayu/p/14359238.html
Copyright © 2020-2023  润新知