【数据结构与算法】总结关于二叉树题型经典面试题

news2024/11/26 3:50:17

【数据结构与算法】二叉树题型经典面试题

  • 1.根据二叉树创建字符串
  • 2.二叉树的层序遍历
  • 3.二叉树的最近公共祖先
  • 4.二叉搜索树与双向链表
  • 5.从前序与中序遍历序列构造二叉树
  • 6.从中序与后序遍历序列构造二叉树
  • 7.二叉树的前序遍历(非递归方法)
  • 8.二叉树的中序遍历(非递归方法)
  • 9.二叉树的后序遍历(非递归方法)

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

在这里插入图片描述
在这里插入图片描述

解题思路:
1.本质上考察的还是前序遍历,只不过要求加上括号,将子树括起来。
2.在递归到左子树之前要加上 ( 括号,在左子树递归结束后,要加上 )括号。
3.在递归右子树之前要加上 ( 括号,在右子树递归结束后,要加上 )括号。
4.题目要求空括号要省略,即为空结点点的位置就不需要再递归进去。(递归前后就将括号加上了)。所以只有不为空结点的位置才需要递归进去。
5.题目还有要求当左子树为空,而右子树不为空时,左子树为空的位置需要加上括号。

class Solution {
public:
      string tree2str(TreeNode* root) {
      if(root==nullptr)
      return "";
      //如果root为空,直接返回空字符串
      string str=to_string(root->val);//要将结点里的数据变成string类型
      
      //相当于前序遍历打印
      if(root->left||root->right)//①当左子树存在时,需要打印括号② 当左子树不存在时,右子树存在,则需要打印
      {
      //递归之前加上(
      str+='(';
      str+=tree2str(root->left);
      str+=')';
      //递归之后加上)
      }
      //当第一个条件为假时才会判断第二个条件,所以当左子树为空,右子树不为空时,也需要打印
      

     if(root->right)//当右子树存在时,需要打印
     {
      str+='(';
      str+=tree2str(root->right);
      str+=')';
     }
     

      return str;
    }
};

2.二叉树的层序遍历

在这里插入图片描述

解题思路
1.二叉树的层序遍历需要使用到队列。
2.题目要求将每层的结点输入到一个vector<vector<.int>>> vv数组里
3.首先判断root是否为空,不为空时,直接将root结点入栈。
4.如何一行一行的获取各个结点呢?每pop掉一个结点,就要将它的左右结点入队列。比如pop掉根结点之后,就要将根节点的左右子树入队列。(当左孩子不为空时入队列,当右孩子不为空时再入队列)
4.根据队列的大小,来确定二叉树每层结点的个数。队列里有几个结点,就循环pop几次,每次pop完,要将pop掉的结点的左右子结点再入队列。循环几次,就会将结点的左右子树都入队列中来,所以这样就可以根据队列中元素的多少确定每层的结点个数。
5.每次pop前将队列里的结点值插入到vector<.int> v数组里,然后再将每层有的元素插入到vv里。
6.当队列为空时,则结束循环。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> vv;
    queue<TreeNode*> q;

    if(root)
    q.push(root);
    //首先将根结点入栈

    //这时栈里就不为空了
    while(!q.empty())
    {

         vector<int> v;
        //根据栈里元素的多少来确定每层的个数
        int num=q.size();
        for(int i=0;i<num;i++)
        {
            TreeNode* top=q.front();
            v.push_back(top->val);
            //每层的元素插入到v里
             q.pop();
           //将元素pop掉后就要将这个元素的左右孩子入栈
           if(top->left)
           q.push(top->left);
           if(top->right)
           q.push(top->right);
            
        }
        //将每层的v插入到vv里
        vv.push_back(v);
    }
    return vv;
    }
};

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

在这里插入图片描述

解题思路①
1.如何判断某个结点是否是两个指定结点的最近公共祖先呢?
2.当指定的两个结点在当前结点的两侧时(左边和右边),就可以判断当前结点就是最近公共祖先。 或者有一个结点是根结点就可以判断该结点是公共祖先。
3.需要写一个查找FInd函数,用来判断结点是否在这颗树。
4.定义4个判断变量,分别是pinleft ,pinright, qinleft,qinright。用来查找p,q是否在左树还是在右树。
5.所以当两个在同一侧树时,公共祖先就不可能是另外一颗树。就直接递归到这一侧去找。比如同时在左边,则递归到左子树去找,同时在右边,则递归到右子树去找。当两个在两次时,直接返回该结点,该节点就是最近公共祖先。
6.时间复杂度O(N*2)

还有一种方法可以将时间复杂度提升到O(N)程度

解题思路②
1.利用栈将结点的路径(从根节点到该结点的路径)给找到并存起来,那么两个结点的路径中的交点,就是公共祖先。就相当于转化为链表相交问题了。
2.就是Find查找过程中将结点入栈。当不是所找结点的路径时就出栈。先入栈,再比较。
3.如果当前结点为空,直接返回false。
4.如果当前结点不为空,先入栈,然后进行比较。如果当前结点是所找结点,直接返回true。
5.走到这里说明,当前结点不是所找结点,那么就需要递归到左子树去找,如果在左子树里,那么直接返回true。
6.走到这里说明,所找结点不在左子树,那么就递归到右子树去找,如果在右子树,那么就直接返回true。
7.走到这里说明,所找结点也不知右子树,这说明当前结点和左右子树都没有,那么该结点肯定不是所找结点的路径,可以将其从栈中pop掉。然后返回false。
8.将两个结点的路径存到两个栈里后,根据链表相交解题原理,让长的路径先走长度差,这里直接pop长度差次。
9.然后比较栈里相同的结点就是公共祖先。

在这里插入图片描述

 // 最近公共祖先--》 孩子在左右两侧的结点就是最近公共祖先
class Solution {
public:
// 查找函数,用来查找node结点是否在该树里
    bool Find(TreeNode* root, TreeNode* node)
    {
        if(root==nullptr)
        return false;
        
        if(root==node)
        return true;

        return Find(root->left,node)||Find(root->right,node);

    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if(root==nullptr)
    return nullptr;
    //其中一个结点为根节点直接可以返回根节点,根据定义可以找到根节点就是公共祖先
    if(root==p||root==q)
    {
        return root;
    }
    //到这里说明p 或 q不是根结点,所以要么在左子树或者在右子树
    //需要写一个能查找p q结点是在左右子树那一步的函数
    bool pinleft,pinright,qinleft,qinright;

    pinleft=Find(root->left,p);//查找p是否在左子树,不在左子树就在右子树
    pinright=!pinleft;

    qinleft=Find(root->left,q);//查找q是否在左子树,不在左子树就在右子树
    qinright =!qinleft;
     
     //p,q两个都在左子树
    if(pinleft&&qinleft)
    {
        return lowestCommonAncestor(root->left,p,q);
    } 
    else if(pinright&&qinright)//p,q两个都在右子树
    {
        return lowestCommonAncestor(root->right,p,q);
    }
    else//p,q两个在两侧
    {
        return root;//直接返回该节点。
    }
    }
};

解题②:

//特殊树会怎么样? 三叉链 二叉搜索树?
 //通过这个题目L:理解 通过Find查找这个过程,在加入一个栈, 可以将一个普通二叉树的路径搞出来
class Solution {
public:
      //查找某个结点的同时将该结点的路径放入栈里
    bool Path(TreeNode* root, TreeNode*node, stack<TreeNode*>& st)
    {
        if(root==nullptr)
        return false;

        //当前结点不为空,首先需要入栈
        st.push(root);
        //入栈以后再进行比较
        if(root==node)
        return true;

        //走到这里表明,当前结点并不是所找的结点,那么就需要递归到左子树去找
        if(Path(root->left,node,st))//如果为真,则说明该结点在左子树,如果为假的,就不走这里。递归到右子树去找
        {
          return true;
        }
        if(Path(root->right,node,st))//如果为真,则说明该结点在右子树,如果为假的,则说明该结点不在右子树
        {
            return true;
        }

        //能走到这里说明,当前结点的左右子树都没有所要找的结点,则说明该结点不可能是所找结点路径
        st.pop();
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath,qPath;
        Path(root,p,pPath);
        Path(root,q,qPath);
      //因为不知道谁的路径长,所以这里两个都比较一下,只会走一个。
        while(pPath.size()>qPath.size())
        {
            pPath.pop();
        }
        while(qPath.size()>pPath.size())
        {
            qPath.pop();
        }

        while(qPath.top()!=pPath.top())
        {
            pPath.pop();
            qPath.pop();
        }

        return pPath.top();
    }
};

4.二叉搜索树与双向链表

在这里插入图片描述

解题思路
1.题目要求二叉搜索树转化成一个排序好的双向链表,那么这里肯定要走中序,因为中序才可以有序。
2.题目要求只能在原树上改动,不能开辟空间。
3.那么就写一个特殊的中序遍历走完,就变成双向链表。
4.中序遍历,左 根 右,这里递归到左子树和递归到右子树是肯定的,要操作的地方就在于根这里
5.要求将左指针变成前驱,右指针变成后继,首先我们要明白,当前结点的右指针指向我们是无法明确的,就像我们不知道明天会发生什么,但左指针我们是可以明确的,就是前一个结点,所以我们可以先将各个结点的左指针改成前驱。要知道前一个结点的位置,我们就要在递归之前记录这个结点。这里我们再传一个参数prev,用来记录每个结点的前一个位置。一开始给nullptr。(注意这个参数需要给引用,因为想要让下一个结点知道上一个结点的改动,就需要用到引用)
6.所每递归到一个结点,就让这个结点的左指针指向prev(也就是前一个结点的位置)。
7.虽然我们不知道每个结点的右指针指向哪里,但我们知道每个结点前一个结点的右指针指向哪里呀,每一个结点的前一个结点的右指针就指向当前结点。我们可以穿越回去,让前一个结点的右指针自己。
8.所以左指针的指向可以在当前结点完成,而右指针的指向需要穿越到前一个结点完成,也就是当前结点能完成左指针的指向,而右指针的指向只能完成前一个结点。
9.题目要求获取双向链表的第一个结点,在二叉树里即最小结点,直接返回最左边结点即可。

class Solution {
public:
    void Inoder(TreeNode* cur,TreeNode* &prev)//prev用来记录当前结点的前一个结点
	{
        if(cur==nullptr)
		return ;

		//走中序遍历
		Inoder(cur->left,prev);
        //根 ->有序
		cur->left=prev;//当前结点的左指针我们是知道的,但右指针是不知道的

		//当前结点是无法知道后一个指针指向那里的,但我可以穿越到前一个结点,将前一个结点的右指针指向我自己,那么前一个结点的右指针就链接上了
      
	   if(prev!=nullptr)
		prev->right=cur;
        //prev要求改变,在整个递归中只有以一个prev

      //在每次递归之前,记录当前结点的位置
		prev=cur;
		//想要让下一次递归看到上一次的改变,就需要用引用,不然看不到
		
     //左指针指向是在当前结点完成的,而右指针的指向是在后一个结点完成的。
		Inoder(cur->right,prev);
	}
    TreeNode* Convert(TreeNode* pRootOfTree) {
        TreeNode* prev=nullptr;
		Inoder(pRootOfTree,prev);

		TreeNode* head=pRootOfTree;
		//返回二叉树中最左结点,这里还有要注意,head必须是不为空才可以走这个循环,不然head为空,就没有左指针
		while(head&&head->left)
		{
			head=head->left;
		}
		return head;
    }
};

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

在这里插入图片描述

解题思路
1.利用前序方式构建二叉树。即首先创建结点,然后递归左子树,递归右子树。
2.怎么创建呢?我们根据前序遍历可以确定根结点,根据中序遍历可以确定根结点的左右区间。一旦知道左右区间我们就可以递归了。
3.首先根据前序遍历创建结点,然后到中序遍历里找到该根节点,并确定其左右区间。
4.然后根据左区间,递归到左子树。根据右区间,递归到右子树。
5.题目给的函数参数不满足我们所需,所以创建一个子函数,我们需要前序数组的下标,需要中序数组的区间。前序的下标要给引用,因为在递归中一直走的都是这个数组。

class Solution {
public:

     //原理:根据前序确定根,中序确定根的左右区间,利用前序遍历方式创建结点
     //需要子函数,唯一我们还需要两个数组的下标

     TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int& prei,int begin,int end)
     {
         //当还右一个结点也要创,当没有结点了,就返回
         if(begin>end)
         return nullptr;
            //前序不断确定根节点,通过中序丘吉尔的左右区间

            TreeNode* newnode=new TreeNode(preorder[prei]);//根据前序确定根,创建根结点

            //再确定该结点在中序中的位置
            int pos=begin;
            while(pos<=end)
            {
                if(preorder[prei]==inorder[pos])
                break;
                else
                ++pos;
            }
            //中序确定左右子树区间
            //[begin   pos-1]  pos  [pos+1,   end ]
            ++prei;
            //确定左右区间后,就可以递归创建左右子树
             newnode->left=_buildTree(preorder,inorder,prei,begin,pos-1);

             newnode->right=_buildTree(preorder,inorder,prei,pos+1,end);
             return newnode;

     }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int x=0;
         return _buildTree(preorder,inorder,x,0,inorder.size()-1);
    }
};

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

在这里插入图片描述

解题思路
1.与上一题类似,只不过这里根据后序和中序来构建二叉树。
2.这里要注意的是后序根节点在哪呢?后序,左右根,最后一个才是根节点,并且根节点前一个是右子树。
3.所以我们在创建完结点后,先递归走的是右子树然后再递归左子树。
4.根据后序确定根节点,根据中序确定结点的左右区间。
5.类似于前一个,需要创建一个子函数,用来获取想要的参数,后序的下标,中序的区间。
后序从最后一个开始,依次往前走。

lass Solution {
public:
//后序遍历 :左 右  根
//后序确定根结点,中序确定左右区间,  创建完根,递归应该先递归创建右子树,再创建左子树

     TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder,int& posi,int begin,int end)
     {
         if(begin>end)
         return nullptr;
             //根据后序最后一个先确定根结点
             TreeNode* newnode =new TreeNode(postorder[posi]);

             //从后序中确定根结点后,再从中序中找到这个结点,从而确定左右区间
             int j=begin;
             while(j<=end)
             {
                 if(inorder[j]==postorder[posi])
                 break;
                 else
                 ++j;
             }
             //这时结点的左右区间就分割出来了
             //[begin  j-1] j  [j+1,  end]
             --posi;
             //首先递归创建右子树
             newnode->right=_buildTree(inorder,postorder,posi,j+1,end);
             //然后再递归创建左子树
             newnode->left=_buildTree(inorder,postorder,posi,begin,j-1);
             return newnode;
     }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int i=postorder.size()-1;
      return _buildTree(inorder,postorder,i,0,inorder.size()-1);

    }
};

7.二叉树的前序遍历(非递归方法)

在这里插入图片描述

解题思路
1.将一颗树看成两部分,左路结点和右子树。
2.前序遍历,我们可以确定最先被访问的是左路各个结点,然后就是从最下面的左路结点的右子树,访问完再访问上一个左路结点的右子树,依次类推。而要实现这样最下面的左路结点的右子树最先被访问,需要用到栈。
3.首先将左路结点全部入栈。(左路结点在入栈之后就已经被访问完了,然后就开始要访问右子树)栈里一旦有元素就说明有右子树要被访问。要访问右树之前先将左路结点pop掉。
4.怎么访问右子树呢?子问题转化,可以将右子树再看成由左路结点和右子树构成,每一个右子树都可以看成由左路结点和右树构成。
5.题目要求放入一个数组里,在访问完结点后,就将结点里的值放入数组里,而栈里的结点是用来找左路结点对应的右树的。

在这里插入图片描述

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
      stack<TreeNode*> st;
      vector<int> v;
      TreeNode* cur=root;
      //用cur表示要一开始要访问的树
      //当栈里还有元素,表明还有右路需要访问
      //在访问右子树之前就会将左路结点pop掉,如果不加上cur的话,最后一个左路结点的右树就不会被访问到,因为这时,栈已经空了。
      while(cur||!st.empty())
      {
          //首先需要将左路结点不断入栈
          while(cur)
          {
              st.push(cur);
              v.push_back(cur->val);
              //将访问完的结点值放入数组里
              cur=cur->left;
          }

          //栈里结点是用来找右路的
          //首先将栈里元素取出来,然后pop掉
          TreeNode* Top =st.top();
          st.pop();

          //用子问题的方式去访问右路
          cur =Top->right;
      }
      return v;
    }
};

8.二叉树的中序遍历(非递归方法)

在这里插入图片描述

解题思路
1.与前序不同的是访问结点的时机不同,前序是根左子树右子树,而中序是先左子树再根然后右子树。
2.前序在入栈之后就访问完根结点了,而中序虽然同样是把左路结点都入栈,在入栈后并不是真正的访问根结点,只有当将左路结点从栈里取出来时,才是真正的访问到这个结点。而取出来这个结点说明它的左路已经被访问完了。比如最下面的左路结点一开始入栈并不是真正访问到,当出栈说明它的左路已经被访问完,它的左路就是空结点,直接可以访问到根结点了(因为左中右顺序)。而访问到根结点后,就可以将根节点值放入数组里。
3.前序中序后序其中本质上就是访问结点的时机不同而已。
4.当根结点访问完,就可以访问右子树了,右子树如何访问呢?子问题转化!

 //先将左路入栈
 //当栈里元素被取出,表明左路结点已经被访问。
 //然后就访问左路结点的右树
 //与前序本质就是访问左路结点的时机不同,前序是在入栈之前就访问了,而中序是在入栈取出之后才访问完。
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
      stack<TreeNode*> st;
      vector<int> v;
      TreeNode* cur=root;
      //用cur表示要一开始要访问的树
      //当栈里还有元素,表明还有右路需要访问
      while(cur||!st.empty())
      { 
          //将左路全部入栈
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
          //首先将栈里元素取出来,然后pop掉,这时才访问完左路
          TreeNode* Top =st.top();
          st.pop();
          v.push_back(Top->val);
          //访问完根结点后就开始访问右树
          //用子问题的方式去访问右路
          cur =Top->right;
      }
   
      return v;
    }
};

9.二叉树的后序遍历(非递归方法)

在这里插入图片描述

解题思路
1.与前序中序不同的是访问结点的时间不同,后序是左右根,根结点是最后再访问。
2 前序是将左路入栈之后就访问完了,中序将左路入栈后并不是真正的访问,而当左路被取出来后才是真正的访问到结点。而后序将左路入栈后不是真正的访问,将左路再取出来时,也不是真正的访问这个结点,而还需要再访问这个左路结点的右树后,回来才算真正的访问到这个结点。而如何判断右树是否被访问过了呢?当右树没有被访问时,前一个访问的结点是谁?(左路结点)当右树被访问完时,前一个访问的结点是谁?(右树结点),所以根据上一次访问的结点是否是右树结点来判断是否访问完。
3.当右树为空时,可以直接去访问这个结点了。当右数不为空时,那么先去访问右子树,如何访问右子树?子问题转化。
4.而当右子为空可以访问这个结点,或者当右树被访问完后,也就可以访问这个结点了。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
     stack<TreeNode*> st;
      vector<int> v;
      TreeNode* cur=root;
      TreeNode*prev=nullptr;
      while(cur||!st.empty())
      {
          //首先将左路全部入栈
          while(cur)
          {
              st.push(cur);
              cur=cur->left;
          }
          //当栈里元素取出来时,表明这个结点的左路已经访问完,而要访问这个结点需要判断右路如何
          TreeNode* top=st.top();
          //右路结点为空,或者上次访问的结点为右路时,则可以访问该结点
          if(top->right==nullptr||prev==top->right)
          {
              v.push_back(top->val);
              //要记录一下上一次访问的结点是哪一个
              st.pop();
               prev=top;
          }
          else
          {
              cur=top->right;
          }

        
      }
      return v;
    }
};

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

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

相关文章

SpringBoot接收参数的8种方式

文章目录 1. 直接把请求参数写在方法的形参中2. 封装一个bean直接来接收3. 原生的HttpServletRequest接收4. PathVariable获取rest风格路径参数5. RequestParam绑定请求参数到方法形参6. RequestBody绑定请求参数到方法形参7. RequestHeader8. CookieValue 1. 直接把请求参数写…

唯一受邀参会通信服务商!融云出席数字经济头部盛会「中数大会」并发言

8 月 16 日-18日&#xff0c;“2023 中国数字经济创新发展大会”&#xff08;下简称“中数大会”&#xff09;在广东省汕头市举办。关注【融云 RongCloud】&#xff0c;了解协同办公平台更多干货。 中数大会由工业和信息化部、广东省人民政府联合主办&#xff0c;以“聚数联侨…

C++ new运算符开辟空间

1 内存四区介绍 代码区&#xff1a;存放函数的二级制代码&#xff0c;由操作系统进行管理的全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值&#xff0c;局部变量等堆区&#xff1a; 由程序员分配和释放&…

点云平面拟合和球面拟合

一、介绍 In this tutorial we learn how to use a RandomSampleConsensus with a plane model to obtain the cloud fitting to this model. 二、代码 #include <iostream> #include <thread> #include <pcl/point_types.h> #include <pcl/common/io.…

kubesphere部署rocketmq5.x,并对外暴露端口

kubesphere是青云开源的k8s管理工具&#xff0c;用户可以方便的通过页面进行k8s部署的部署&#xff0c;rocketmq则是阿里开源的一款mq平台&#xff0c;现在版本为5.1.3版本&#xff0c;较比4.x版本的rocketmq有比较大的调整&#xff1a;比如客户端的轻量化&#xff08;统一通过…

MS1022高精度时间测量(TDC)电路,应用于超声波热量表、水表、激光测距

产品简述 MS1022 是一款高精度时间测量电路&#xff0c;内部集成了模拟比 较器、模拟开关、施密特触发器等器件&#xff0c;从而大大简化了外 围电路。同时内部增加了第一波检测功能&#xff0c;使抗干扰能力大 大提高。通过读取第一个回波脉冲的相对宽度&#xff0c;用户可…

Spring6.0官方文档示例:(27)配置文件中bean定义的继承关系

一、实体类 package cn.edu.tju.domain;public class DerivedTestBean {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {t…

几种常见的递归算法

阶乘 这个比较简单就不说了。 int factorial(int n) {if (n < 0){return 0;}else if (n 1){return 1;}else {return n * factorial(n - 1);} }fibonacci 如此简单的算法&#xff0c;复试的时候竟然写错了&#xff01;&#x1f633;囧&#xff01; int fibonacci(unsigne…

高忆管理:a股印花税调整利好股市吗?印花税下调利好股市吗?

在股票市场上&#xff0c;印花税并不是一成不变的&#xff0c;政府会依据实际情况进行调整&#xff0c;那么&#xff0c;a股印花税调整利好股市吗&#xff1f;印花税下调利好股市吗&#xff1f;下面高忆管理为大家预备了相关内容&#xff0c;以供参阅。 股票印花税一般是指投资…

Transformer是否真正理解了自然语言的语义信息,还是单纯的模式识别

论文引用 此篇阅读笔记与思考主要针对以下两篇论文&#xff1a; Climbing towards NLU: On Meaning, Form, and Understanding in the Age of Data Transformer Feed-Forward Layers Are Key-Value Memories 本文将讨论第一篇论文所引发的思考&#xff08;第一篇论文的详细解…

企业级快速开发平台,助力企业走入流程化管理,创造高效办公!

要想实现高效办公&#xff0c;创造流程化管理新时代&#xff0c;需要借助一些优秀平台来实现目标。企业级快速开发平台是当前较为流行的软件平台&#xff0c;拥有多项典型功能&#xff0c;可以摒弃传统办公带来的效率低下、难维护等各种矛盾&#xff0c;一起创造流程化管理和数…

入行嵌入式,你离高薪还差一步!

近几年越来越多的人了解了嵌入式这个高薪、前景好的行业&#xff0c;许多同学也加入了嵌入式学习的队伍中&#xff0c;但对于自己未来在嵌入式的发展方向还是难以抉择&#xff0c;这里为大家答疑解惑一波。 熟悉嵌入式领域的同学都知道&#xff0c;嵌入式可以从软件和硬件两个方…

全链路数据湖开发治理解决方案2.0重磅升级,全面增强数据入湖、调度和治理能力

简介&#xff1a; 阿里云全链路数据湖开发治理解决方案能力持续升级&#xff0c;发布2.0版本。解决方案包含开源大数据平台E-MapReduce(EMR) &#xff0c; 一站式大数据数据开发治理平台DataWorks &#xff0c;数据湖构建DLF&#xff0c;对象存储OSS等核心产品。支持EMR新版数据…

C++继承-补充

本期对继承的知识进行一些补充&#xff0c;还没看过之前对继承讲解的建议先看之前的 C继承_KLZUQ的博客-CSDN博客 本期补充知识为菱形继承以及菱形虚拟继承相关知识 class A { public:virtual void func1(){cout << "A::func1" << endl;} public:int _…

平板用的触控笔什么牌子好?开学必买电容笔清单

开学季马上就要到来了&#xff0c;自从iPad的Pencil火了之后&#xff0c;国内又陆续推出了一些新的产品&#xff0c;比如平替之类的&#xff0c;有的质量非常好&#xff0c;有的价格非常实惠&#xff0c;还能被大多数人所接受。不过&#xff0c;这里面有不少的产品&#xff0c;…

手把手教你在云环境炼丹:Stable Diffusion LoRA 模型保姆级炼制教程

很多同学都想要自己的专属AI模型&#xff0c;但是大模型的训练比较费时费力&#xff0c;不太适合普通用户玩。AI开发者们也意识到了这个问题&#xff0c;所以就产生了微调模型&#xff0c;LoRA就是其中的一种。在AI绘画领域&#xff0c;只需要少量的一些图片&#xff0c;就可以…

七夕情侣飞行棋游戏限定版本源码/解锁版

七夕情侣飞行棋限定版本源码已经发布&#xff01;这是一款专为情侣打造的桌游&#xff0c;让您与您的另一半一起感受浪漫的体验。 更为重要的是&#xff0c;这个版本已经移除了路由器限制&#xff0c;解锁了全部功能&#xff0c;而且没有任何加密措施&#xff0c;您只需将源码…

将ChatGPT集成整合到业务中时,3个要做和3个不要做的事项

​关于ChatGPT的讨论甚多&#xff0c;毫无疑问的是&#xff0c;几乎每个人都应该使用它&#xff0c;无论用于个人生活问题的解答还是工作中简化日常任务。越来越多的行业也正在探索这项技术的应用场景&#xff0c;从优化客户服务体验、简化旅行计划到便捷的内容创作等&#xff…

day 35 | ● 343. 整数拆分 ● 96.不同的二叉搜索树

343. 整数拆分 他是有三个数进行比较&#xff0c;原来的dp[i]、dp[j] * (i - j)、j*(i - j)。为什么第二个不包含第三个呢&#xff0c;因为我们设定的dp为至少两个数的乘积&#xff0c;所以dp[j]不包含j本身。 func integerBreak(n int) int {dp : make([]int, n 1)dp[1] 0d…

python 画二部图

1. 特色二部图 修改节点与边颜色、大小等 import networkx as nx import matplotlib.pyplot as plt plt.figure(设备-用户关系图, figsize(4, 6)) # 设置画布大小list_fid [1, 2, 3, 4] # 添加设备节点 list_uid ["a", "b", "c"] # 添加用…