二叉树进阶oj题【二叉树相关10道oj题的解析和c++代码实现】

news2024/9/28 15:15:51

目录

  • 二叉树进阶oj题
    • 1.根据二叉树创建字符串
    • 2.二叉树的层序遍历
    • 3.二叉树的层序遍历 II
    • 4.二叉树的最近公共祖先
    • 5.二叉搜索树和双向链表
    • 6.从前序与中序遍历序列构造二叉树
    • 7.从中序和后序遍历序列来构造二叉树
    • 8.二叉树的前序遍历,非递归迭代实现
    • 9.二叉树中序遍历 ,非递归迭代实现
    • 10.二叉树的后序遍历 ,非递归迭代实现

二叉树进阶oj题

1.根据二叉树创建字符串

根据二叉树创建字符串:

image-20240923095720602

分析:

image-20240924214607725

先递归左子树,再递归右子树,每递归到一个节点就套娃一个()。

要注意,当一个根节点的左孩子不存在右孩子存在时,要用一个()表示左孩子

class Solution {
public:
    string tree2str(TreeNode* root)
    {
        // str作为最后的输出的字符串
        string str;

        // 要求前序遍历——根,左子树,右子树
        str += to_string(root->val);

        // 这里要分类讨论:
        //1.左不为空
        //2.左空,右不为空 这个情况要保留一个左的括号
        if (root->left)
        {
            str += "(";
            str += tree2str(root->left);
            str += ")";
        }
        else if (root->right)
        {
            str += "()";
        }

        if (root->right)
        {
            str += "(";
            str += tree2str(root->right);
            str += ")";
        }

        return str;
    }
};

2.二叉树的层序遍历

二叉树的层序遍历

image-20240923095738735

分析:

层序遍历就采用一个队列就可以实现。一个节点出来要记得带它的做右子树进节点

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root)
    {
        vector<vector<int>> vv;
        queue<TreeNode*> _q; // 通过队列实现层序

        // 传空树进行不需要遍历了。
        if (root)
            _q.push(root);


        while (!_q.empty())
        {
            // 通过控制每层的数据个数,来达到精确的输出二叉树每层的数据
            // 意思就是 当第n层数据出完之后,第n+1层的数据个数就是此时的q.size()
            int levelSize = _q.size();
            vector<int> v;
            for (size_t i = 0; i < levelSize; i++)
            {
                TreeNode* front = _q.front();
                _q.pop();
                v.push_back(front->val);

                // 弹出节点后要带该节点的左右孩子
                if (front->left)
                    _q.push(front->left);

                if (front->right)
                    _q.push(front->right);
            }

            // 此时v就是装好了一层的数据,将其尾插到vv中
            vv.push_back(v);
        }

        return vv;
    }
};

3.二叉树的层序遍历 II

二叉树的层序遍历 II:

image-20240923095754004

分析:

这道题和第2道题的思路是一样的,只需要将最后的结果逆置,也就是vv逆置一下,再输出就是自下而上的层序遍历

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root)
    {
        vector<vector<int>> vv;
        queue<TreeNode*> _q; // 通过队列实现层序

        // 传空树进行不需要遍历了。
        if (root)
            _q.push(root);


        while (!_q.empty())
        {
            // 通过控制每层的数据个数,来达到精确的输出二叉树每层的数据
            // 意思就是 当第n层数据出完之后,第n+1层的数据个数就是此时的q.size()
            int levelSize = _q.size();
            vector<int> v;
            for (size_t i = 0; i < levelSize; i++)
            {
                TreeNode* front = _q.front();
                _q.pop();
                v.push_back(front->val);

                // 弹出节点后要带该节点的左右孩子
                if (front->left)
                    _q.push(front->left);

                if (front->right)
                    _q.push(front->right);
            }

            // 此时v就是装好了一层的数据,将其尾插到vv中
            vv.push_back(v);
        }

        // 只要逆置一下,就是自底向上的层序遍历
        reverse(vv.begin(), vv.end());

        return vv;
    }
};

4.二叉树的最近公共祖先

二叉树的最近公共祖先

image-20240923095858455

分析:

image-20240923092914747

解决思路:

如果是第一种情况,只要判断出p、q其中一个是根节点或者p、q不在同一子树,就可以知道根节点就是公共祖先

如果不是第一种情况,就说明p、q存在于同一个子树,就要递归到其左树去寻找p、q的位置,左树没找到,就递归到右树去找到p、q的位置,在判断是什么情况。

代码如下:

class Solution {
public:

    bool Find(TreeNode* root, TreeNode* f)
    {
        if (root == NULL)
            return false;

        // f和root不是相同节点,就递归到左子树去找,左子树找不到就递归到右树找
        return root == f || Find(root->left, f) || Find(root->right, f);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        // 如果穿了个空树进来,就不用判断了
        if (root == NULL)
            return NULL;

        // 只要p、q有一个是root,其公共祖先就是root了
        if (q == root || p == root)
            return root;

        // 定义四个变量来表示p、q的位置
        bool pInLeft, pInRight, qInLeft, qInRight;

        pInLeft = Find(root->left, p); // 去左子树找p
        pInRight = !pInLeft; // 左子树没找到就在右子树

        qInLeft = Find(root->left, q); //去左子树找q
        qInRight = !qInLeft;

        // 如果一个在左子树,一个在右子树,公共祖先就是root
        if ((pInLeft && qInRight) || (pInRight && qInLeft))
            return root;

        // 如果都在左子树,就要递归到左子树去找
        if (pInLeft && qInLeft)
            return lowestCommonAncestor(root->left, p, q);

        // 如果都在右子树,就要递归到右子树去找
        if (pInRight && qInRight)
            return lowestCommonAncestor(root->right, p, q);

        return NULL;
    }
};

5.二叉搜索树和双向链表

二叉搜索树和双向链表

image-20240923114827276

分析:

将二叉搜索树转换为双向链表其实就是修改树节点的left和right指针按照中序遍历指向对应的节点。

这里我们让left指针指向上一个节点,right指向下一个节点

image-20240923103919808

但是这里有个问题,当我们通过中序遍历递归到一个节点的时候,这个节点的right指针是无法指向下一个节点的,因为拿不到另外一层递归深度的节点。因此这里采用双指针来解决这个问题

如下图所示:

image-20240923103645032

注意:在传双指针到函数进行调用的时候,prev要注意得传址或者传引用调用。cur不需要传引用和传址,函数内部不对cur进行赋值操作,不需要改变cur本身,要改变的是cur内部的指针

代码如下:

struct TreeNode 
{
	int val;
	struct TreeNode* left;
	struct TreeNode* right;
	TreeNode(int x)
		:val(x)
		,left(NULL)
		,right(NULL) 
	{}
}; 


class Solution {
public:
	// 这里TreeNode*&的引用一定要加,不然就用二级指针。这样才是传址调用
	void ConvertList(TreeNode* cur, TreeNode*& prev)
	{
		if (cur == nullptr)
			return;

		// 中序遍历
		ConvertList(cur->left, prev);
		// 这里才是对当前根节点进行处理的地方,在这里连接上一个节点和下一个节点
		cur->left = prev; // cur的left指针指向上一个节点

		// 只要prev不为空的情况下,就可以让其right指针指向下一个节点
		if (prev)
			prev->right = cur;

		//这里对prev进行赋值,一定要注意是传值还是传址,传值调用会导致上一层的prev无法改变
		prev = cur; // 迭代

		ConvertList(cur->right, prev);
	}

	TreeNode* Convert(TreeNode* pRootOfTree)
	{
		// 空树,无法转换
		if (pRootOfTree == nullptr)
			return nullptr;

		// 双指针解决节点连接问题
		TreeNode* prev = nullptr;
		TreeNode* cur = pRootOfTree;
		ConvertList(cur, prev);

		// 此时的双向链表就已经连接完了。
		// 此时的树结构被破坏了,但是依旧可以根据left指针或者right指针来找
		//一直找上一个节点,来找到第一个节点,或者一直找下一个节点,找到尾节点
		TreeNode* head = pRootOfTree;
		// 这里不用考虑head是否为nullptr,而导致解引用空指针崩溃
		// 因为pRootOfTree走到这里不可能是nullptr
		while (head->left != nullptr)
		{
			head = head->left;
		}

		return head;
	}
};

6.从前序与中序遍历序列构造二叉树

从前序与中序遍历序列构造二叉树

image-20240923202340573

思路分析:

image-20240923163814834

image-20240923164252890

代码实现如下:

struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};


class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder, int& prei, int inbegin, int inend)
    {
        // 先构建一个根节点
        TreeNode* root = new TreeNode(preorder[prei]);

        // 找到中序遍历中根节点的位置
        int rooti = inbegin;
        while (rooti <= inend)
        {
            if (inorder[rooti] == preorder[prei])
                break;
            else
                ++rooti;
        }

        // 此时找到了中序遍历的根节点,这个时候可以将中序遍历化为3个区间
        // 左子树区间, 根节点,右子树区间
        // [inbegin, rooti-1] rooti [rooti+1, inend]

        //这个时候还要判断左区间和右区间是否存在,才能去进行递归构建
        if (inbegin <= rooti - 1)
            root->left = _buildTree(preorder, inorder, ++prei, inbegin, rooti - 1);
        else
            root->left = nullptr; // 左子树不存在了,连接空

        // 构建完左子树之后,才构建右子树,同样的也要判断,是否存在右子树区间
        if (rooti + 1 <= inend)
            root->right = _buildTree(preorder, inorder, ++prei, rooti + 1, inend);
        else
            root->right = nullptr;

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
        // 如果是空的就不用构建了
        if (inorder.empty() || preorder.empty())
            return nullptr;

        //确定根节点的下标和中序遍历的范围
        int prei = 0;// 这个是前序遍历的下标,prei指向的是待构建的节点
        int inbegin = 0;
        int inend = inorder.size() - 1;

        TreeNode* ret = _buildTree(preorder, inorder, prei, inbegin, inend);

        return ret;

    }
};

注意:

这道题的本质还是通过preorder中的前序遍历来构建二叉树,但是我们并不知道prei所指向的节点到底是左子树的节点还是右子树的节点。因此我们通过中序遍历来划分区间,从而来确定prei所指向的节点是左子树的还是右子树的节点。

7.从中序和后序遍历序列来构造二叉树

从中序与后序遍历序列构造二叉树

image-20240923202352277

分析:

这个和第六题是非常像的,不一样的是,这里通过后序遍历来确定根节点的位置。中序排序的作用还是划分左子树和右子树的区间,这样才能确定根据后序遍历序列的节点左子树的节点还是右子树的节点、

image-20240924110323775

当构建完3这个根节点之后,构建20这个根节点,递归进去。

image-20240924110517201

依次类推,最终构建出右子树,在构建左子树

要想彻底理解过程,可以画出每个节点被创建出来后是如何连接到一起的。

代码如下:

class Solution {
public:
    TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder, int& posi, int inbegin, int inend)
    {
        TreeNode* root = new TreeNode(postorder[posi]);

        //在中序遍历序列中找到根节点
        int rooti = inbegin;
        while(rooti <= inend)
        {
            if(inorder[rooti] == postorder[posi])
                break;
            else
                ++rooti;
        }

        // 找到了根节点就要划分区域————左子树、根、右子树
        // [inbegin, rooti - 1] rooti [rooti + 1, inend]
        if(rooti+1 <= inend)
            root->right = _buildTree(inorder, postorder, --posi, rooti+1, inend);
        else   
            root->right = nullptr;
        
        // 先构建完右子树后,再来构建左子树
        if(inbegin <= rooti-1)
            root->left = _buildTree(inorder, postorder, --posi, inbegin, rooti-1);
        else
            root->left = nullptr;

        return root;
    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
    {
        // 如果是空的就不用构建了
        if(inorder.empty() || postorder.empty())
            return nullptr;

        int posi = postorder.size() - 1;
        int inbegin = 0;
        int inend = inorder.size() - 1;

        TreeNode* ret = _buildTree(inorder, postorder, posi, inbegin, inend);

        return ret;
    }
};

要注意:

无论是第六题还是本题,prei和posi的形参都必须加上引用或者是指针,不然的话,递归深了,对其进行++,上一层递归深度的函数的posi是不会变化的。

8.二叉树的前序遍历,非递归迭代实现

二叉树的前序遍历

image-20240924105419187

image-20240924090659133

在递归实现前序遍历二叉树的时候,我们发现访问的节点可以分为两类:

  1. 左路节点
  2. 左路节点的右子树

image-20240924090158694

因此我们只需要将整颗树分成左路节点和左路节点的右子树来访问就行了

那如何访问左路节点呢——我们需要借助一个栈

将所有左路节点放到一个栈里

image-20240924092428891

此时有三个圈,代表当前树的三个左路节点的右子树部分

image-20240924092540048

然后我们取栈里的左路节点出来,依次访问他们的右子树部分。

要注意这个访问右子树的过程是将右子树也看成一棵树来看待的,也就是说将这个右子树分成左路节点和左路节点的右子树两个部分查看。这个思路就是模仿递归的思路。只是我们通过迭代来实现这个过程

这个去栈的左路节点访问右子树部分的过程如下图所示:

image-20240924093226002

image-20240924093643900

image-20240924093900621

image-20240924094144478

image-20240924094309057

image-20240924094524242

image-20240924094732557

此时cur为空,栈也为空,意味访问结束,树已前序遍历完成

代码如下:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        // 借助栈实现非递归的前序遍历二叉树
        stack<TreeNode*> st;

        TreeNode* cur = root;
        // 当cur和栈都为空的时候意味着遍历完成
        while(cur || !st.empty())
        {
            // 访问当前cur这棵树的所有左路节点并放到栈中
            while(cur)
            {
                ret.push_back(cur->val);
                st.push(cur);
                cur = cur->left;
            }

            // 取栈内的左路节点,并访问其右子树
            TreeNode* top = st.top();
            st.pop();
            cur = top->right;
        }

        // 此时ret中存放着前序遍历的数字
        return ret;
    }
};

9.二叉树中序遍历 ,非递归迭代实现

二叉树的中序遍历

image-20240924105541553

这个题和前序遍历的思路是一样的,唯一的区别就是让左路节点入栈的时候,不能访问,取左路节点的时候,才访问该节点,并访问该节点的右子树。

image-20240924103211326

代码如下:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        stack<TreeNode*> st; // 借助栈实现非递归中序遍历

        TreeNode* cur = root;
        // 当cur和栈同时为空,才意味着遍历完成
        while(cur || !st.empty())
        {
            // 将当前cur这棵树的所有左路节点放到栈中
            while(cur)
            {
                // 中序遍历,这里只入栈,不访问节点
                st.push(cur);
                cur = cur->left;
            }

            // 取左路节点出来,访问该左路节点
            //并且访问该左路节点的右子树
            TreeNode* top = st.top();
            st.pop();
            ret.push_back(top->val); // 放问该左路节点
            cur = top->right; // 指向该左路节点右子树,下一循环访问该树
        }
        
        // 返回ret,中序遍历的结果
        return ret;
    }
};

10.二叉树的后序遍历 ,非递归迭代实现

二叉树的后序遍历

image-20240924105911259

这里的后序遍历,需要在前两题的思路上变动一下。

大致思路不变,还是将整颗树分成左路节点和左路节点的右子树两个部分。将当前树的左路节点放到栈里,然后从栈中取左路节点出来,由于是后序,不访问左路节点,也不能将其从栈内弹出,要先访问其右子树

这里访问右子树有两种情况:

  1. 如果右子树是空,那么就访问这个左路节点,并弹出

  2. 如果右子树不为空,那么就访问右子树,并不弹出该左路节点【仍然将这个右子树分两个部分处理】

但是有一个难点就在这里,如果右子树不为空,由于上一个左路节点未弹出,如下图的2节点,就会访问两次,这个时候如何区分5这个右子树是否被访问过了?

image-20240924120044115

如果区分不出来那么程序就会陷入死循环。

解决思路:

  1. 弄一个储存标志位的栈,只要遇到右子树不是空,就给该右子树弄一个标志位,并存到栈中,等到第二次访问该节点的时候,通过取出这个标志位,判断该节点是否被访问过。
  2. 双指针,一个指针指向当前访问节点,一个指针指向上一个节点,因为后序遍历顺序是左子树、根、右子树、**因此当我想访问一个左路节点的时候,其双指针一定待在该左路节点的右孩子当中。比如访问2,双指针的另一个指针就在5。**但是我第一次取到2,不能访问2,要判断其2的右子树是否被访问过,只要双指针不在其右子树,就说明没有被访问过。

代码如下:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        stack<TreeNode*> st; // 用栈辅助实现非递归后序遍历二叉树

        // 用双指针解决——如何判断左路节点的右子树是否被访问过的问题
        TreeNode* cur = root;
        TreeNode* lastNode = nullptr; // lastNode由于记载栈顶的左路节点的右子树是否被访问过
        
        // 当cur和栈都为空,才是遍历完二叉树
        while(cur || !st.empty())
        {
            // 先把当前树的所有左路节点放到栈里
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }

            // 拿到栈顶的左路节点
            TreeNode* top = st.top();
            // 由于是后序,先判断栈顶元素的右子树是否被访问过.
            if(top->right == nullptr || lastNode == top->right)
            {
                // 只要右子树为空,或者是右子树被访问过,那么就不需要在访问当前左路节点的右子树。
                ret.push_back(top->val); // 访问当前左路节点
                st.pop(); // 可以弹出该左路节点
                lastNode = top; // 更新lastNode的位置,保持其一直位于top的上一个访问节点
            }
            else
            {
                // 访问当前左路节点的右子树
                cur = top->right;
            }
        }

        // 返回后序遍历
        return ret;
    }
};

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

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

相关文章

日志工具spdlog全解析:理论、安装、使用与实践(C++)

文章目录 前言spdlog 与 glog spdlog介绍内容日志等级输出格式 使用步骤同步日志输出异步日志输出封装一个日志输出类对日志输出类的测试 安装 前言 在编写项目时&#xff0c;通过日志追踪程序错误或其他情况出现的位置是十分重要的&#xff0c;对于不太复杂的场景&#xff0c…

突发:Sam万字长文,OpenAI o1超越人类,o1模型训练原理、微调、能力来源-AI已死,大模型当立

OpenAl o1大模型&#xff1a;原理、突破、前景及影响 北京时间2024年9月13日凌晨&#xff0c;OpenAI正式发布了新的人工智能模型o1&#xff08;o是orion猎户座&#xff0c;1代表从头再来&#xff0c;也意味着后续将出现更多序列&#xff09;&#xff0c;就是此前OpenAI一直在高…

烟雾污染云层检测系统源码分享

烟雾污染云层检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

嵌入式学习--LinuxDay04

嵌入式学习--LinuxDay04 shell脚本 1.1数组 1.1.1数组的赋值 1.1.2数组的调用 1.2函数 1.2.1函数的定义方式 1.2.2函数的调用 2.分文件编程 2.1源文件 2.2头文件 3.编译工具 3.1 gcc编译工具 3.2 gdb调试 4.make工具 4.1定义 4.2Makefile格式 4.3Makefile管理多个文件 4.4Makef…

【笔记】X射线的衍射方向

X射线在晶体中的衍射&#xff0c;实质是大量原子散射波互相干涉的结果。 衍射花样有两个特征&#xff1a; 衍射方向&#xff08;衍射线在空间的分布规律&#xff09;&#xff1a;由晶胞的大小、形状和位向决定。 衍射强度&#xff1a;由原子的种类以及它在晶胞中所处的位置决…

56 门控循环单元(GRU)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录门控循环单元&#xff08;GRU&#xff09;门控隐状态重置门和更新门候选隐状态隐状态 从零开始实现初始化模型参数定义模型训练与预测 简洁实现小结练习 门控循环单元&#xff08;GRU&#xff09; 之前我们讨论了如何在循环神经网络中计算梯…

PREDATOR: Registration of 3D Point Clouds with Low Overlap

Abstract 这篇文章介绍了一种新的点云配准模型-Predator。该模型专注于处理低重叠的点云对&#xff0c;它更加关注于重叠区域的处理&#xff0c;其新颖之处在于一个重叠的注意块&#xff0c;作用是用于两个点云的潜在编码之间的早期信息交换。该模型大大提高了低重叠场景下的配…

AI跟踪报道第58期-新加坡内哥谈技术-本周AI新闻: OpenAI动荡时刻和Meta从未如此动人

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

深度学习与数学归纳法

最近发现&#xff0c;深度学习可以分为两个主要的阶段&#xff0c;分别是前向推理以及反向传播&#xff0c;分别对应着网络的推理和参数训练两个步骤。其中推理有时候也称为归纳推理。 在做参数训练的时候&#xff0c;本质上是在利用历史数据求网络参数的先验分布&#xff1b; …

leetcode每日一题day15(24.9.25)——公司命名

思路&#xff1a;首先如果没有相同的后缀&#xff0c;则无论只要不是相同的首字母交换都不会出现重复情况&#xff0c;如果有重复后缀&#xff0c;则还需多增加个不能和&#xff0c;首字符与另一相同后缀字串的首字符相同的字串交换。 主要矛盾已经明确&#xff0c;则可对矛盾…

MySql5.7.26安装和配置

一.下载&#xff1a; 地址MySQL :: Download MySQL Community Server 1、选择版本 根据自己需要选择32位或64位版本&#xff08;这里选择64位&#xff09;点击下载 进入到下载页面按下图操作 2.解压文件放置位置&#xff1a;这边将下载的文件解压到D:Software 下 解压后内部文…

Linux---文件io

1.系统调用 由操作系统实现并提供给外部应用程序的编程接口。(Application Programming Interface&#xff0c;API)。是应用程序同系统之间数据交互的桥梁。 C标准函数和系统函数调用关系。一个helloworld如何打印到屏幕。 man手册中一共有九卷&#xff0c;其中一卷就有讲到系…

快速了解graphql特点

graphql--快速了解graphql特点 1.它的作用2.demo示例2.1依赖引入2.2定义schema2.3定义GrapQL端点2.4运行测试2.5一些坑 今天浏览博客时看到graphQL,之前在招聘网站上第一次接触,以为是图数据查询语言, 简单了解后,发现对graphQL的介绍主要是用作API的查询语言,不仅限于图数据查…

目标检测系列(三)yolov2的全面讲解

YOLOv2&#xff08;论文原名《YOLO9000: Better, Faster, Stronger》&#xff09;作为该系列的第二个版本&#xff0c;对原始YOLO进行了显著的改进&#xff0c;进一步提高了检测速度和准确度。在精度上利用一些列训练技巧&#xff0c;在速度上应用了新的网络模型DarkNet19&…

个性化大语言模型:PPlug——让AI更懂你

在当今数字化转型的时代&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经成为了不可或缺的工具&#xff0c;它们在自然语言理解、生成和推理方面展现了非凡的能力。然而&#xff0c;这些模型普遍采用的是“一刀切”的方式&#xff0c;即对于相同的输入给予所有用户相…

828华为云征文|部署多功能集成的协作知识库 AFFiNE

828华为云征文&#xff5c;部署多功能集成的协作知识库 AFFiNE 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 AFFiNE3.1 AFFiNE 介绍3.2 AFFiNE 部署3.3 AFFiNE 使用 四、…

【深度学习】(10)--ResNet残差网络

文章目录 ResNet残差网络1. 传统卷积神经网络的问题1.1 梯度消失和梯度爆炸1.2 退化问题 2. 解决问题2.1 梯度消失与爆炸2.2 退化问题 3. 残差结构结构归纳 4. BN&#xff08;Batch Normalization&#xff09; 总结 ResNet残差网络 ResNet 网络是在 2015年 由微软实验室中的何…

ComfyUI 完全入门:必备插件

前言 大家好&#xff0c;我是每天分享AI应用的月月&#xff01; ComfyUI 是一个基于 Stable Diffusion 的AI绘画创作工具&#xff0c;最近发展势头特别迅猛&#xff0c;但是 ComfyUI 的上手门槛有点高&#xff0c;用户需要对 Stable Diffusion 以及各种数字技术的原理有一定的…

小麦生长状态检测系统源码分享

小麦生长状态检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

基于SpringBoot的新冠检测信息管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 国内外在该方向的研究现状及分析 新型冠状病毒肺炎疫情发生以来&#xff0c;中国政府采取积极的防控策略和措施&#xff0c;经过两个多月的不懈努力&#xff0c;有效控制了新发病例的増长&#xff0c;本地传播已经趋于完全控制…