【数据结构】_7.二叉树

news2024/7/6 6:55:58

目录

1.树形结构

1.1 树的概念

1.2 树的相关概念

1.3 树的表示

1.4 树在实际中的应用—表示文件系统的目录树结构

​编辑​2.二叉树

2.1 概念

2.2 特殊二叉树

 2.3 二叉树的性质

2.4 二叉树的存储结构

2.4.1 顺序存储结构(数组存储结构)

2.4.2 链式存储结构

2.5 二叉树的基本操作

2.5.1 二叉树的深度优先遍历

2.5.2 二叉树的广度优先遍历

2.5.3 二叉树的结点统计

2.5.4 二叉树的叶子结点统计

 2.5.5 二叉树第K层结点统计

 2.5.6 获取二叉树的高度

2.5.7 检测值为value的元素是否存在

2.5.8 判断一棵树是否为完全二叉树

2.6 二叉树的非递归方法

2.6.1 非递归实现前序遍历

2.6.2 非递归实现中序遍历

2.6.3 非递归实现后序遍历


1.树形结构

1.1 树的概念

树是一种非线性数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合,把它称为树是因为它看起来像一棵倒挂的树,根在上,枝叶在下。

① 根节点是一个没有前驱结点的特殊结点;

② 除根节点外,其余结点被分为M(M>0)个互不相交的集合T1,T2,T3...Tm,其中每一个集合Ti(1<=i<=m)又是一棵结构与树类型相似的子树,每棵树的根节点有且仅有一个前驱,可以有0个或多个后继;

③ 因此,树是递归定义的;

PS:树形结构中,子树之间不能有交集,即除了根节点之外,每个结点有且仅有一个直接前驱;

1.2 树的相关概念

(1)结点的度:一个结点含有的子树的个数,如A结点的度为6;

(2)叶结点或终端结点:度为0的结点,如H、I、P、Q、K、L、M、N;

(3)非终端结点或分支结点:度不为0的结点,如:D、E、F、G、J;

(4)双亲结点或父节点:含有子结点的结点,称该结点为其子结点的父结点,如A是B的父结点;

(5)孩子结点或子结点:一个结点含有的子树的根节点称为该结点的子结点,如B是A的子结点;

(6)兄弟结点:具有相同父结点的结点,如B和C是兄弟结点;

(7)数的度:一棵树中最大的结点的度称为数的度,如上图树的度为6;

(8)结点的层次:从根开始定义,根为第一层,根的子结点为第二层,以此类推;

(9)树的高度或深度:树中结点的最大层次,如上图树的高度或深度为4;

(10)堂兄弟结点:双亲在同一层的结点称为堂兄弟,如H和I互为堂兄弟结点;

(11)结点的祖先:从根到该结点所经分支上的所有结点,如A是所有结点的祖先;

(12)子孙:以某节点为根的子树中任一结点都成为该结点的子孙,如所有节点都是A的子孙;

(13)森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3 树的表示

树的存储相较于线性表要复杂得多,既要存储值域,也要存储结点与结点之间的关系;

树有很多种表达方式,如双亲表示法、孩子表示法、孩子-双亲表示法。

最常用的是:左孩子-右兄弟表示法。

图示:

 代码表示:

class Node{
    int val;     // 数据域
    Node firstChild;   // 第一个孩子引用
    Node nextBrother;  // 下一个兄弟引用
}
//注意此处的兄弟指的是亲兄弟而非堂兄弟,即此处指向的兄弟有相同的祖先

1.4 树在实际中的应用—表示文件系统的目录树结构


​2.二叉树

2.1 概念

(1)一个二叉树的结点是一个有限集合,该集合:① 或者为空 ② 有一个根节点加上两个别称为左子树和右子树的二叉树组成;

 (2)特点:

    ① 不存在度大于2的结点;

    ② 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树;

(3)任意一种二叉树都是由①空树②只有根节点③只存在左子树④只存在右子树⑤左右子树均存在这五种情况复合而成;

2.2 特殊二叉树

(1)满二叉树:

 每层节点数都是最大值的二叉树,即满足层数为k,结点总数是2^k-1的二叉树就是完全二叉树。

(2)完全二叉树:

对于深度为k的二叉树,前k-1层的结点都是满的,最后一层不满但满足,存在的结点是从左向右是连续的

 2.3 二叉树的性质

(1)若规定根结点层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点

(2)若规定根结点层数为1,则深度为h的二叉树的最大结点数是2^k-1

(3)对任何一个二叉树,如果度为0的结点个数为n0,度为2的分支节点个数为n2,则有n0=n2+1;

(4)若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1)(以2为底);

例1:某二叉树共有399个结点,其中199个度为2的结点,则该二叉树中的叶子节点数为(B)

A.不存在这样的二叉树   B.200    C.198   D. 199   

解析:根据第三条性质,叶子结点数即度为0的结点数,根据第三条性质得答案。

例2:在具有2n个结点的完全二叉树中,叶子结点个数为(A)

A.n  B.n+1 C. n-1  D.n/2

解析:度为0的结点记为n0,度为1的结点记为n1,度为2的结点记为n2,根据题意有:

n0+n1+n2=2n,结合第三条性质有:n2=n0-1,代入有2*n0-1+n1=2n,对于一个完全二叉树来

说,度为1的结点只能有0个或1个,此处若n1=0,则n0为小数,故而n1只能为1,所以度为0的结

点个数为n。

例3:一个完全二叉树结点数为531个,那么这棵树的高度为(B)

A.11 B. 10  C.8  D.12

解析:高度为h的完全二叉树,结点范围是[2^(h-1),2^h-1],代入选项进行上下限计算得答案。

例4:一个具有767个结点的完全二叉树,其叶子结点个数为(B)

A.383  B. 384  C.385  D.386

解析略,同例二思路

2.4 二叉树的存储结构

二叉树的存储有两种存储方式:

2.4.1 顺序存储结构(数组存储结构)

① 一般使用数组存储只适合表示完全二叉树或满二叉树,若是一般二叉树会存在很多空间浪费;

在现实使用中,只有对才会使用数组来存储;

② 二叉树的顺序存储在物理上是一个数组,在逻辑上是一个二叉树。

③ 同时顺序存储可以根据下标计算结点父子关系:

知父求子:leftchild=parent*2+1,leftchild=parent*2+2;

知子求父:(parent-1)/2;

2.4.2 链式存储结构

二叉树的链式存储是通过一个一个的结点引用起来的,常见的表示方式有:

(1)二叉表示法(孩子表示法):

class Node{
    int val;   // 数据域
    Node left;   // 左孩子引用(常代表以左孩子为根的整个左子树)
    Node right;  // 右孩子引用(常代表以右孩子为根的整个右子树)
}

 (2)三叉表示法(孩子-双亲表示法):

class Node{
    int val;   // 数据域
    Node left;   // 左孩子引用(常代表以左孩子为根的整个左子树)
    Node right;  // 右孩子引用(常代表以右孩子为根的整个右子树)
    Node parent; // 当前结点的根节点
}

 孩子-双亲表示法主要应用在平衡树,本文采取孩子表示法构建二叉树;

2.5 二叉树的基本操作

2.5.1 二叉树的深度优先遍历

深度优先遍历包括前序遍历、中序遍历与后序遍历;

前序遍历:访问根结点的操作发生在遍历其左右子树之前;(跟->左子树->右子树)

中序遍历:访问根结点的操作发生在遍历其左右子树之中;(左子树->根->右子树)

后序遍历:访问根结点的操作发生在遍历其左右子树之后;(左子树->右子树->根)

以#表示空:

前序遍历:1 2 3 # # # 4 5 # # 6 # # 

中序遍历:# 3 # 2 # 1 # 5 # 4 # 6 # 

后序遍历:# # 3 # 2  # # 5 # # 6 4 1

基于以下二叉树结构:

其递归实现代码如下:

    // 前序遍历:根  左子树  右子树  递归
    public void preOrder(TreeNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+"  ");
        preOrder(root.left);
        preOrder(root.right);
    }
    // 中序
    public void inOrder(TreeNode root){
        if(root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+"  ");
        inOrder(root.right);
    }
    // 后序
    public void postOrder(TreeNode root){
        if(root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+"  ");
    }

创建对象后分别调用,输出结果为:

  

注:除过空返回值的写法外,也可以令深度优先遍历有返回值:

(1)遍历思路写法:

    List<Character> ret = new ArrayList<>();
    public List<Character> preorderTraversal(TreeNode root){
        if(root == null){
            return ret;
        }
        ret.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return ret;
    }

(2)子问题思路写法:

    public List<Character> preorderTraversal(TreeNode root){
        List<Character> ret = new ArrayList<>();
        if(root == null){
            return ret;
        }
        //System.out.print(root.val+" ");
        ret.add(root.val);

        List<Character> leftTree = preorderTraversal(root.left);
        ret.addAll(leftTree);

        List<Character> rightTree = preorderTraversal(root.right);
        ret.addAll(rightTree);
        return ret;
    }

2.5.2 二叉树的广度优先遍历

创建一个队列,令cur从root开始遍历,在根节点不为空的条件下,将root入队列,依次判断root.left和root.right是否为空,非空则入队列,当队列不为空时,出栈对首元素并令root = cur;

    public void levelOrder(TreeNode root){
        if(root == null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode cur = queue.poll();
            System.out.print(cur.val+" ");
            if(cur.left != null){
                queue.offer(cur.left);
            }
            if(cur.right != null){
                queue.offer(cur.right);
            }
        }
    }

输出结果为:

  

2.5.3 二叉树的结点统计

(1)思路1:子问题思路:

    public int size(TreeNode root){
        // 左树结点+右树结点+根节点
        // 写法1:
        //return root == null? 0: size(root.left)+size(root.right)+1;
        // 写法2:
        if(root == null){
            return 0;
        }
        int leftSize = size(root.left);
        int rightSize = size(root.right);
        return leftSize + rightSize + 1;
    }

(2)思路2:遍历思路:

    public int nodeSize;
    public void size2(TreeNode root){
        if(root == null){
            return;
        }
        nodeSize++;
        size2(root.left);
        size2(root.right);
    }

测试代码为:

        System.out.println("子问题思路求二叉树结点:");
        System.out.println(binaryTree.size(binaryTree.root));
        System.out.println("遍历思路求二叉树结点:");
        binaryTree.size2(binaryTree.root);
        System.out.println(binaryTree.nodeSize);

输出结果为:

2.5.4 二叉树的叶子结点统计

(1)思路1:子问题思路:

    public int getLeafNodeCount(TreeNode root){
        if(root == null){
            return 0;
        }
        if(root.left==null && root.left == null){
            return 1;
        }
        int leftTreeNode = getLeafNodeCount(root.left);
        int rightTreeNode = getLeafNodeCount(root.right);
        return leftTreeNode+rightTreeNode;
    }

(2)思路2:遍历思路:

    public int leafNode = 0;
    public void getLeafNodeCount2(TreeNode root){
        if(root == null){
            return;
        }
        if(root.left == null && root.right == null){
            leafNode++;
        }
        getLeafNodeCount2(root.left);
        getLeafNodeCount2(root.right);
    }

测试代码为:

        System.out.println("子问题思路求叶子节点的个数为:");
        System.out.println(binaryTree.getLeafNodeCount(binaryTree.root));
        System.out.println("遍历思路求叶子结点个数为:");
        binaryTree.getLeafNodeCount2(binaryTree.root);
        System.out.println(binaryTree.leafNode);

输出结果为:

 2.5.5 二叉树第K层结点统计

(仅展示子问题思路)

    public int getKLevelNodeCount(TreeNode root, int k){
        if(root == null){
            return 0;
        }
        if(k==1){
            return 1;
        }
        int leftTreeNode = getKLevelNodeCount(root.left,k-1);
        int rightTreeNode = getKLevelNodeCount(root.right,k-1);
        return leftTreeNode+rightTreeNode;
    }

测试代码为:

        TestBinaryTree binaryTree = new TestBinaryTree();
        binaryTree.root = binaryTree.createTree();
        System.out.println("请输入要查询结点的层数:");
        Scanner scanner = new Scanner(System.in);
        int k = scanner.nextInt();
        System.out.println("第"+k+"层结点数为:");
        System.out.println(binaryTree.getKLevelNodeCount(binaryTree.root,k));

输出结果为:

 2.5.6 获取二叉树的高度

    public int getHeight(TreeNode root){
        // 二叉树高度是左右子树高度的较大值+1
        if(root==null){
            return 0;
        }
        int leftTreeHeight = getHeight(root.left);
        int rightTreeHeight = getHeight(root.right);
        return (leftTreeHeight>rightTreeHeight)?leftTreeHeight+1:rightTreeHeight+1;
    }

测试代码为:

        TestBinaryTree binaryTree = new TestBinaryTree();
        binaryTree.root = binaryTree.createTree();
        System.out.println("当前二叉树高度为:");
        System.out.println(binaryTree.getHeight(binaryTree.root));

输出结果为:

2.5.7 检测值为value的元素是否存在

    public TreeNode find(TreeNode root, char val){
        // 前序遍历二叉树
        if(root == null){
            return null;
        }
        if(root.val == val){
            return root;
        }
        TreeNode leftTree = find(root.left, val);
        if(leftTree != null){
            return leftTree;
        }
        TreeNode rightTree = find(root.right, val);
        if(rightTree != null){
            return rightTree;
        }
        return null;
    }

测试代码为:

        TestBinaryTree binaryTree = new TestBinaryTree();
        binaryTree.root = binaryTree.createTree();
        System.out.println("请输入要查询的value值:");
        char value = (char)System.in.read();
        TestBinaryTree.TreeNode ret = binaryTree.find(binaryTree.root, value);
        if(ret != null){
            System.out.println(ret.val);
        }else {
            System.out.println(ret);
        }

输出结果为·:
      

2.5.8 判断一棵树是否为完全二叉树

创建一个队列,在根结点不为空的前提下,先将根结点入队列,然后每弹出一个队首元素,就将其左右孩子结点入队列,直到队首元素为空,若此时队列中元素全为空,则为完全二叉树,否则就不是完全二叉树;

代码:

    public boolean isCompleteTree(TreeNode root){
        if(root == null){
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);     // 将根结点入队列
        while( !queue.isEmpty()) {
            // 每弹出一个队首元素,就将该元素的左右孩子入队列;
            TreeNode cur = queue.poll();
            if (cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            } else {
                //  一直出队列队首元素直至队首元素为null
                break;
            }
        }
        
        while(!queue.isEmpty()){
            TreeNode tmp = queue.poll();
            if(tmp != null){
                return false;
            }
        }
        return true;
    }

测试代码为:

        TestBinaryTree binaryTree = new TestBinaryTree();
        binaryTree.root = binaryTree.createTree();
        System.out.println("判断是否为完全二叉树:");
        System.out.println(binaryTree.isCompleteTree(binaryTree.root));
        System.out.println();

输出结果为:

 基于原二叉树,删除E结点的右孩子H结点,再次测试结果如下:

2.6 二叉树的非递归方法

2.6.1 非递归实现前序遍历

定义cur结点用于遍历二叉树,从根结点root开始,令cur依次遍历左子树,在结点左孩子不为空的前提下,将结点逐个入栈,每入栈一个结点,就打印一个结点,当遇到左孩子为空的结点后,弹出栈顶元素并令cur为其右孩子;

    public void preOrderNor(TreeNode root){
        if(root == null){
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while(cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.val + " ");
                cur = cur.left;
            }
            // 此时为cur为空但栈不为空:
            // 令cur为栈顶元素的右孩子即可
            TreeNode top = stack.pop();
            cur = top.right;
        }
    }

2.6.2 非递归实现中序遍历

    public void inOrderNor(TreeNode root){
        if(root == null){
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while(cur != null || !stack.isEmpty()){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            System.out.print(top.val+" ");
            cur = top.right;
        }
    }

2.6.3 非递归实现后序遍历

   public void postOrderNor(TreeNode root){
        if(root == null){
            return;
        }
        TreeNode cur = root;
        TreeNode prev = null;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while(cur != null || !stack.isEmpty()){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if(top.right == null || top.right == prev){
                // 栈顶元素没有右孩子,根据左->右->根,可以直接打印根结点的值
                System.out.print(top.val+" ");
                stack.pop();
                prev = top;
            }else {
                // 栈顶元素有右孩子,还需遍历当前栈顶元素结点的右子树
                cur = top.right;
            }
        }
    }

非递归实现前中后序遍历的测试代码如下:

        TestBinaryTree binaryTree = new TestBinaryTree();
        binaryTree.root = binaryTree.createTree();
        System.out.println("非递归实现前序遍历:");
        binaryTree.preOrderNor(binaryTree.root);
        System.out.println();
        System.out.println("非递归实现中序遍历:");
        binaryTree.inOrderNor(binaryTree.root);
        System.out.println();
        System.out.println("非递归实现后序遍历:");
        binaryTree.postOrderNor(binaryTree.root);
        System.out.println();

 输出结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/903329.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode--HOT100题(36)

目录 题目描述&#xff1a;146. LRU 缓存&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;146. LRU 缓存&#xff08;中等&#xff09; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache…

引人关注的领域 ---- 信号稀疏表示

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在学习摘录和笔记专…

redis实战-缓存数据解决缓存与数据库数据一致性

缓存的定义 缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪&#xff0c;这在实际开发中对企业讲,对产品口碑,用户评价都是致命的;所以企业非常重视缓存…

基于蜉蝣算法优化的BP神经网络(预测应用) - 附代码

基于蜉蝣算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于蜉蝣算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.蜉蝣优化BP神经网络2.1 BP神经网络参数设置2.2 蜉蝣算法应用 4.测试结果&#xff1a;5.Matlab代码 摘要…

MySQL8.0.26-Linux版安装

MySQL8.0.26-Linux版安装 1. 准备一台Linux服务器 云服务器或者虚拟机都可以; Linux的版本为 CentOS7; 2. 下载Linux版MySQL安装包 MySQL :: Download MySQL Community Server (Archived Versions) 3. 上传MySQL安装包 4. 创建目录,并解压 mkdir mysql ​ tar -xvf mysql-8…

网站老域名跳转到新域名有哪些方法?内网穿透内网主机让外网访问

在网站服务器变更及本地主机搭建时&#xff0c;我们经常会遇到老域名地址跳转到新URL的配置&#xff0c;一些朋友还会面对无公网IP让外网访问的问题。今天我们来了解下网站老域名跳转到新域名有哪些方法&#xff0c;以及如何通过内网穿透实现内网主机让外网访问。 网站老域名跳…

【Unity小技巧】Unity2D TileMap的探究(最简单,最全面的TileMap使用介绍)

文章目录 前言介绍一、TileMap简单的使用1、创建Unity工程2、Tilemap的使用2.1、导入素材图片2.2、切割图片2.3、创建画板2.4、创建瓦片2.5、创建网格2.6、在网格上刷瓦片2.7、解决瓦片没有占满格子的问题2.8、解决瓦片之间有缝隙的问题2.9、擦除瓦片2.10、区域瓦片绘制2.11、瓦…

适合上班族做的4个低门槛的副业兼职

对于大多数职场中人来说&#xff0c;如果没有在30岁之后获得晋升&#xff0c;获得更好的发展平台&#xff0c;可能就会感到工作缺乏足够的吸引力了。当我们只有一份工作的时候&#xff0c;就好比把鸡蛋放在一个篮子里&#xff0c;把自己的青春放在一家公司里。这也就好比单一的…

华盛顿大学Baker实验室率先设计出双稳态结构蛋白质

在蛋白质世界&#xff0c;“结构决定功能”是一条基本原则。因此&#xff0c;很多人可能认为&#xff0c;一个蛋白质就应该有一个唯一确定的结构&#xff0c;使得它能够去执行确定的生物学功能。其实&#xff0c;在真实的世界中&#xff0c;蛋白质大多都是处于一种不断起伏的动…

MongDB【CRUD练习-条件查询-文档关系】

练习1-CRUD // 进入test数据库 use test; // 查询文档内容 db.students.find(); // 显示当前数据库中所有集合 show collections; // 向数据库的user集合中插入一个文档 db.users.insertOne({username: "lyh"} ); // 查看当前数据库中所有的集合 发现users集合被创建…

信号处理--基于EEG脑电信号的眼睛状态的分析

本实验为生物信息学专题设计小项目。项目目的是通过提供的14导联EEG 脑电信号&#xff0c;实现对于人体睁眼和闭眼两个状态的数据分类分析。每个脑电信号的时长大约为117秒。 目录 加载相关的库函数 读取脑电信号数据并查看数据的属性 绘制脑电多通道连接矩阵 绘制两类数据…

《强化学习:原理与Python实战》——可曾听闻RLHF

前言&#xff1a; RLHF&#xff08;Reinforcement Learning with Human Feedback&#xff0c;人类反馈强化学习&#xff09;是一种基于强化学习的算法&#xff0c;通过结合人类专家的知识和经验来优化智能体的学习效果。它不仅考虑智能体的行为奖励&#xff0c;还融合了人类专家…

LeetCode算法递归类—二叉树的右视图

目录 199. 二叉树的右视图 题解&#xff1a; 目标&#xff1a; 思路&#xff1a; 过程&#xff1a; 代码&#xff1a; 运行结果&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所…

使用渲染纹理(RenderTexture)来实现3D视觉

如上图的效果&#xff0c;使用2D场景&#xff0c;通过摄像头的改动&#xff0c;使其看起来像是3D效果一样。 Nintendo Switch上刚推出的《超级马里奥》中&#xff0c;有一些关卡混合了2D和3D的画面&#xff0c; 一般来说&#xff0c;摄像机会直接渲染到电脑屏幕&#xff1b;…

【C语言练习】数组OJ题

目录 一.消失的数字思路1&#xff1a;思路2&#xff1a; 二.移除元素三.轮转数组四.删除有序数组中的重复项五.合并两个有序数组 一.消失的数字 题目&#xff1a; 思路1&#xff1a; 数组是从0加到N&#xff0c;所以把0到N的数加起来减去数组中的值&#xff0c;结果就是消失…

阿里云ECS服务器和轻量应用服务器区别?怎么选择?

阿里云轻量应用服务器和云服务器ECS有什么区别&#xff1f;ECS是专业级云服务器&#xff0c;轻量应用服务器是轻量级服务器&#xff0c;轻量服务器使用门槛更低&#xff0c;适合个人开发者或中小企业新手使用&#xff0c;可视化运维&#xff0c;云服务器ECS适合集群类、高可用、…

Cadence 仿真

电路的学习离不开仿真和实践&#xff0c;主流的仿真软件有很多&#xff0c;有用功pretues和mutisim&#xff0c;这次主要是工作中使用cadence&#xff0c;而且带有比较强大的仿真工具Pspice&#xff0c;所以选择了它 &#xff0c;我使用的版本是cadence 17.4自带的。官方提供了…

ViT模型架构和CNN区别

目录 Vision Transformer如何工作 ViT模型架构 ViT工作原理解析 步骤1&#xff1a;将图片转换成patches序列 步骤2&#xff1a;将patches铺平 步骤3&#xff1a;添加Position embedding 步骤4&#xff1a;添加class token 步骤5&#xff1a;输入Transformer Encoder 步…

leetcode 213. 打家劫舍 II

2023.8.20 本题是 打家劫舍 的进阶版&#xff0c;房屋之间形成一个环了&#xff0c;也就是第一个房屋和最后一个房屋不能一起偷了。那么能偷的情况分为下列三种&#xff1a; 不考虑偷首房间。不考虑偷尾房间。不考虑偷首尾房间。 第三种情况包含于第一和第二种情况了&#xff…

CSerialPort教程4.3.x (1) - CSerialPort项目简介

CSerialPort教程4.3.x (1) - CSerialPort项目简介 前言 CSerialPort项目是一个基于C/C的轻量级开源跨平台串口类库&#xff0c;可以轻松实现跨平台多操作系统的串口读写&#xff0c;同时还支持C#, Java, Python, Node.js等。 CSerialPort项目的开源协议自 V3.0.0.171216 版本…