专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结

news2024/10/6 1:30:25

目录

搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜

1.深度优先遍历 vs 深度优先搜索(dfs)

2.宽度优先遍历 vs 宽度优先搜索(bfs)

2.关系图暴力枚举一遍所有的情况

3.拓展搜索问题全排列

决策树

1. 计算布尔⼆叉树的值(medium)

解析:

1.函数头

2.函数体

3.函数出口

总结:

2. 求根节点到叶节点数字之和(medium)

解析:​编辑

总结:

3. ⼆叉树剪枝(medium)

总结:

4. 验证⼆叉搜索树(medium)

解析:

策略一:中序遍历,判断这个二叉树是否有序

策略二:剪枝

总结:

5. ⼆叉搜索树中第 k ⼩的元素(medium)

解析:

总结:

6. ⼆叉树的所有路径(easy)

解析:

总结:

穷举vs暴搜vs深搜vs回溯vs剪枝

什么是回溯算法

7. 全排列(medium)

解析:

1)暴力枚举:

2)递归优化:

2.设计代码:

全局变量

dfs函数

细节问题

总结:

8. ⼦集(medium)

解析:

解法一:

1.决策树

2.设计代码

全局变量

dfs

解法二:

1.画决策树

2.设计代码

总结:


搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜

1.深度优先遍历 vs 深度优先搜索(dfs)

2.宽度优先遍历 vs 宽度优先搜索(bfs)

那么遍历只是形式,目的是搜索

2.关系图
暴力枚举一遍所有的情况

搜索(暴搜) dfs

3.拓展搜索问题
全排列

决策树

废话不多说,直接进入例题:
 

1. 计算布尔⼆叉树的值(medium)

题目比较长,但是还是比较好理解的,0,1,2,3分别代表false,true,|,&
然后在这这个决策树上通过运算,算出最后这颗树的结果

解析:

递归函数的调用:

主要就是分三步,当主问题与子问题相同的时候:

1.函数头

2.函数体

3.函数出口

/**
 * Definition for a binary tree node.
 * 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:
    bool a[2]={false,true};
    bool evaluateTree(TreeNode* root) {
        if(root->left==nullptr||root->right==nullptr) return a[root->val];

        bool left=evaluateTree(root->left);
        bool right=evaluateTree(root->right);

        return root->val==2?left|right:left&right;
    }
};

总结:

只要能分析出当前问题的相同子函数,就可以得出函数体里面的内容,通过所有相同的子函数的内容进行一步步操作就能完成当前函数的任务。

2. 求根节点到叶节点数字之和(medium)

题意还是比较好理解的,就是对从根节点开始一直到叶子节点,计算每个节点当前值不断*10最后所有叶子节点的和

解析:

这种题目计算每个叶子节点的方法一眼就是dfs,先递归到叶子节点,然后就开始相加。

以下是同一种dfs的两种思想:

1.定义全局变量ret,然后每次递归到叶子节点的时候就开始进行相加,那么我就是用一个字符串s来保存每一层的临时变量,这样可以达到回溯的效果,起始不要字符串保存,只有用presum来存储临时变量也是ok的,都能存的下最终的和,然后每次到叶子节点ret就进行相加,知道加完所有叶子节点的值就完成,返回ret

唯一需要注意的就是,在传入dfs的时候就要立刻加上当前节点的值,这样就不会漏掉当前节点的某一位,因为只要到叶子节点就要开始返回上一层了,为了防止叶子节点的值给漏掉。

/**
 * Definition for a binary tree node.
 * 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:
    int ret=0;
    int sumNumbers(TreeNode* root) {
        string s;
        dfs(root,s);
        return ret;
    }

    void dfs(TreeNode* root,string s)
    {
        s+=to_string(root->val);

        if(root->left==nullptr&&root->right==nullptr)
        {
            ret+=stoi(s);
            return;
        }

        if(root->left) dfs(root->left,s);
        if(root->right) dfs(root->right,s);
    }
};

2.就是用presum来记录临时变量,不需要字符串到整形,整形到字符串的各种转换,因为最后的结果int也能存下。

看到上面的图,就能看出,如果我存临时变量presum,那么dfs返回的就是当前节点下所有叶子节点的和,那么整个二叉树就都变成了一个子问题,就是要求头节点下所有叶子节点的和。

函数头:int dfs(root,presum);

出口:就是当到达叶子节点的时候,那么就返回当前叶子节点的presum

函数体:用ret来记录当前节点下所有左右子树中,叶子节点的和,在当前节点左子树不为空下,传入dfs(root->left,presum);在当前节点右子树不为空下,传入dfs(root->right,presum);来求出当前节点下的左右子树的所有叶子节点的和

最后返回ret

/**
 * Definition for a binary tree node.
 * 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:
    int sumNumbers(TreeNode* root) {
        return dfs(root,0);
    }

    int dfs(TreeNode* root,int presum)
    {
        presum=presum*10+root->val;

        if(root->left==nullptr&&root->right==nullptr) return presum;

        int ret=0;//记录当前节点下,所有叶子节点的值
        if(root->left) ret+=dfs(root->left,presum);
        if(root->right) ret+=dfs(root->right,presum);
        return ret; //返回给上一层
    }
};

总结:

像这种带有回溯类的问题,只需要考虑清楚带上的临时变量不会再中途被改变,并且再返回上一层稳定即可。

3. ⼆叉树剪枝(medium)

本题,题意比较绕,但是就是删掉所有子树全为0的节点

解析:

因为计算机不可能知道当前节点下左右子树的所有节点是否全为0,所以就要完全遍历到叶子节点在开始判断,判断叶子节点是否为0 如果是就直接置为空,并且返回空,否则就返回当前节点,不改变。

经过上面的思考,发现要先解决完所有的左子树和右子树,然后在考虑当前的节点是否为0,且左右子树是否为空,所以就完全是一个后序遍历。

1.函数头:再前面的分析里面要返回当前节点的情况,是否为空,否则就返回当前节点。说明函数头是带有返回值的。

Node* dfs(root);

2.函数体:

由于是后序遍历,先访问所有左子树,再访问右子树。然后进行判断当前节点

root->left=dfs(root->left);

root->right=dfs(root->right);

判断:如果当前节点的左右子树都为空,并且当前节点值为0,就说明这个节点也可以被删掉

if(root->left==nullptr&&root->right==nullptr&&root->val==0) root=nullptr;

return root;//将当前节点的值,返回给上一层

3.递归出口:当前节点为空的时候就返回空

if(root==nullptr) return nulltpr;

/**
 * Definition for a binary tree node.
 * 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* pruneTree(TreeNode* root) {
        if(root==nullptr) return nullptr;

        root->left=pruneTree(root->left);
        root->right=pruneTree(root->right);

        if(root->left==nullptr&&root->right==nullptr&&root->val==0) root=nullptr; 
        return root;//返回给上一层
    }
};

总结:

写的代码很简单,但是要想清楚每一步还是很不容易,多注意细节问题,多思考,一个题目要反复思考才能被吸收。

4. 验证⼆叉搜索树(medium)

题意很简单,只要证明该树是不是二叉搜索树

解析:

策略一:中序遍历,判断这个二叉树是否有序

用prev来记录二叉树的中序的根节点,就是当前节点左子树的最右边的一个节点

要保证该二叉树是平衡二叉树,就要一直保证prev < root->val 那么就能满足条件,一旦打破了就返回false

那么:

1.函数头:bool dfs(root)

2.函数体:

弄弄左子树:bool left=dfs(root->left);

中序判断:bool ret = false;

                  if(prev<root->val) ret=true;
                  prev = root->val;

弄弄右子树:bool right=dfs(root->right);

3.出口条件:

当节点访问到空的时候,证明没有问题,返回true

/**
 * Definition for a binary tree node.
 * 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:
    long prev=LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;
        bool left=isValidBST(root->left);

        bool ret=false;
        if(root->val>prev) ret=true;
        prev=root->val;

        bool right=isValidBST(root->right);

        return left&&right&&ret;
    }
};

策略二:剪枝

上面策略一是访问了所有的节点,但是如果只要满足有一个节点不满足平衡二叉树的条件,不满足升序,那么就要返回false,不在往后遍历。

那么只需要再判断左子树的时候证明他是false 或者 再判断当前值不满足升序的时候都返回false就能完成剪枝操作,不在往后执行

/**
 * Definition for a binary tree node.
 * 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:
    long prev=LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;
        bool left=isValidBST(root->left);
        if(left==false) return false;

        bool ret=false;
        if(root->val>prev) ret=true;
        prev=root->val;
        if(ret==false) return false;

        bool right=isValidBST(root->right);

        return left&&right&&ret;
    }
};

总结:

回溯、剪枝真的没有那么神秘,再递归里面百分之99都要用到回溯,剪枝只是再我们能完成条件之后再考虑优化,我们可以尝试以下剪枝。

5. ⼆叉搜索树中第 k ⼩的元素(medium)

题意很简单,中序遍历k次的值就是第k小的元素

解析:

设置两个全局变量,ret,count,那么当count==k的时候,说明dfs再中序遍历里面已经遇到了k次中序遍历的值,得到了第k小的值

1.函数头:

void dfs(root);

2.函数体:

中序遍历,遍历到第k次时找到第k小的值:

dfs(root->left);

++count; if(count==k) ret=root->val;

dfs(root->right);

3.出口条件:

知道root==nullptr || ret != -1 就return;只要ret被改变就可以进行剪枝 

/**
 * Definition for a binary tree node.
 * 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:
    int ret=-1;
    int _k;
    int count=0;
    int kthSmallest(TreeNode* root, int k) {
        _k=k;
        dfs(root);
        return ret;
    }

    void dfs(TreeNode* root)
    {
        if(root==nullptr||ret!=-1) return;
        dfs(root->left);
        if(++count==_k) ret=root->val;
        dfs(root->right);
    }
};

总结:

这题真的很简单,通过上面的练习,就只需要一次中序遍历就可以得到第k小的值。

6. ⼆叉树的所有路径(easy)

题意很简单,将从根节点到叶节点的所有路径放在字符串内进行返回。

解析:

虽然这题很简单,但只是有这个简单题来突破其他的难题,我们需要考虑到很多细节问题:

回溯     ->      恢复现场 的因果关系,是因为有了回溯才出现的恢复现场,不能本末倒置了。
只要有递归,那么就绝对伴随之回溯,只要有深度优先遍历,就会存在恢复现场。

为了回溯恢复现场的时候,那么就要考虑我们的参数就不能设置为全局变量,只需要把他设置为dfs的参数,那么就不需要对全局变量进行修改或删除。再每一层的临时变量都是存储当前位置的参数,不会被后面递归影响。

再考虑路径值的时候,就只需要考虑前序遍历然后添加到字符串内即可。

/**
 * Definition for a binary tree node.
 * 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:
    vector<string> ret;
    vector<string> binaryTreePaths(TreeNode* root) {
        string s;
        dfs(root,s);
        return ret;
    }

    void dfs(TreeNode* root,string s)
    {
        if(root==nullptr) return;

        s+=to_string(root->val);
        if(root->left==nullptr&&root->right==nullptr) ret.push_back(s);
        else s+="->";
        
        dfs(root->left,s);
        dfs(root->right,s);
    }
};

总结:

这里对于回溯和恢复现场真的有很强的表现,强烈建议深刻理解以下恢复现场时,把参数当作临时变量真的很方便,就不需要自己再进行操作。

穷举vs暴搜vs深搜vs回溯vs剪枝

什么是回溯算法

回溯算法是⼀种经典的递归算法,通常⽤于解决组合问题、排列问题和搜索问题等。
回溯算法的基本思想:从⼀个初始状态开始,按照⼀定的规则向前搜索,当搜索到某个状态⽆法前进时,回退到前⼀个状态,再按照其他的规则搜索。回溯算法在搜索过程中维护⼀个状态树,通过遍历状态树来实现对所有可能解的搜索。
回溯算法的核⼼思想:“试错”,即在搜索过程中不断地做出选择,如果选择正确,则继续向前搜
索;否则,回退到上⼀个状态,重新做出选择。回溯算法通常⽤于解决具有多个解,且每个解都需要搜索才能找到的问题。
回溯算法的模板

void backtrack(vector<int>& path, vector<int>& choice, ...) {
 // 满⾜结束条件
 if (/* 满⾜结束条件 */) {
 // 将路径添加到结果集中
 res.push_back(path);
 return;
 }
 // 遍历所有选择
 for (int i = 0; i < choices.size(); i++) {
 // 做出选择
 path.push_back(choices[i]);
 // 做出当前选择后继续搜索
 backtrack(path, choices);
 // 撤销选择
 path.pop_back();
 }
}
其中, path 表⽰当前已经做出的选择, choices 表⽰当前可以做的选择。在回溯算法中,我们需要做出选择,然后递归地调⽤回溯函数。如果满⾜结束条件,则将当前路径添加到结果集中;否则,我们需要撤销选择,回到上⼀个状态,然后继续搜索其他的选择。
回溯算法的时间复杂度通常较⾼,因为它需要遍历所有可能的解。但是,回溯算法的空间复杂度较低,因为它只需要维护⼀个状态树。在实际应⽤中,回溯算法通常需要通过剪枝等⽅法进⾏优化,以减少搜索的次数,从⽽提⾼算法的效率。

7. 全排列(medium)

题意很简单,就是枚举所有可能的排列情况,那么废话不多说就是话决策树。

解析:

1)暴力枚举:

两层三层循环还可以枚举,如果要排列100层的数,那简直不可能,只能借助递归来思考。

2)递归优化:

1.画出决策树:越详细越好

2.设计代码:

全局变量

int [][] ret

int [] path

bool [] check 实现剪枝

dfs函数

就需要关系某一个节点在干什么事情

细节问题

回溯:

1.干掉path最后一个元素

2.修改check数组

剪枝

递归出口:遇到叶子节点就直接添加结果

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    bool check[7];
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums);
        return ret;
    }

    void dfs(vector<int>& nums)
    {
        if(path.size()==nums.size())
        {
            ret.push_back(path);
            return;
        }

        for(int i=0;i<nums.size();i++)
        {
            if(check[i]==false)
            {
                path.push_back(nums[i]);
                check[i]=true;
                dfs(nums);
                path.pop_back();
                check[i]=false;
            }
        }
    }
};

总结:

最重要的就是画出决策树,越细致越好,然后通过决策树来观察代码该如何书写。

8. ⼦集(medium)

题意很简单,就是返回数组nums的所有子集。

解析:

解法一:

1.决策树

2.设计代码

全局变量

vector<vector<int>> ret; //来记录整体传入的子集
    vector<int> path;  //设置全局变量,来保证传参,然后进行手动删除

dfs

细节问题:剪枝,回溯,递归出口

传入nums后,要考虑当前位置是否选择,分为选择和不选择两种

如果选择,那么就是ret.push_back(path+nums[i])

不选择就是ret.push_back(path)

但是这里要注意的就是不选择要在选择前面,这样方便后面选择后的手动删除。再就是dfs传入后就是传入到下一层,i+1,表示的就是下一层的层数,此时回溯到这一层i也不会被改变。

递归出口:就是在i的层数在nums.size()的时候就进行最后的添加,然后进行返回。

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    
    int check[10];
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums,0);

        return ret;
    }

    void dfs(vector<int>& nums,int i)
    {
        if(nums.size()==i)
        {
            ret.push_back(path);
            return;
        }
        
        //不选
        dfs(nums,i+1);
        path.push_back(nums[i]);
        
        //选
        dfs(nums,i+1);
        path.pop_back();
    }
};

解法二:

1.画决策树

2.设计代码

全局变量

vector<vector<int>> ret; //来记录整体传入的子集
    vector<int> path;  //设置全局变量,来保证传参,然后进行手动删除

dfs

细节问题:回溯 剪枝 递归出口 

只用关心每层进去后当前nums下标值的后面的值,前面的值不用考虑

例如:在1中选2,1中选3不选2,就是在for循环内进行的,当进入下一层选2,回来这个数组就会删掉2,i++,再次进入下一层选3.

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums,0);
        return ret;
    }

    void dfs(vector<int>& nums,int k)
    {
        ret.push_back(path);

        for(int i=k;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            dfs(nums,i+1);
            path.pop_back();
        }
    }
};

总结:

我觉得最关键的就是画出决策图然后再进行思考递归出口或者函数体里面的内容,像这一题就是跟上一题决策树完全不同,思考的方向就完全不同。

总结一下吧~这章对我的进步真的很大,希望对你也是!!!

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

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

相关文章

CF2013E Prefix GCD

【题目大意】 给定一个长度为 n n n 的数列 a 1 … n a_{1 \dots n} a1…n​&#xff0c;你可以将 a 1 … n a_{1 \dots n} a1…n​ 按照任意顺序进行重排&#xff0c;使得&#xff1a; ∑ i 1 n gcd ⁡ { a 1 , a 2 , a 3 , … , a n } \sum\limits_{i1}^{n}\gcd\left \{…

10.5学习

1.GateWay GateWay⽬标是取代Netflflix Zuul&#xff0c;它基于Spring5.0SpringBoot2.0WebFlux等技术开发&#xff0c;提供统⼀的路由⽅式&#xff08;反向代理&#xff09;并且基于 Filter(定义过滤器对请求过滤&#xff0c;完成⼀些功能) 链的⽅式提供了⽹关基本的功能&…

探索 Python 虚拟环境的奥秘:virtualenv 的魔法世界

文章目录 探索 Python 虚拟环境的奥秘&#xff1a;virtualenv 的魔法世界背景&#xff1a;为何选择 virtualenv&#xff1f;虚拟环境的守护者&#xff1a;virtualenv 是什么&#xff1f;安装 virtualenv&#xff1a;简单几步&#xff0c;开启隔离之旅掌握 virtualenv 的基本用法…

Relu激活

ReLU&#xff08;Rectified Linear Unit&#xff09;激活函数 是卷积神经网络&#xff08;CNN&#xff09;以及许多深度学习模型中最常用的激活函数之一。它的主要作用是引入非线性&#xff0c;使模型能够学习和表达更复杂的特征。以下是对ReLU激活函数的详细解释。 1. ReLU的…

C语言进阶版第16课—自定义类型:结构体

文章目录 1. 结构体类型的声明和初始化2. 结构体自引用3. 结构体内存对齐3.1 结构体内存对齐规则3.2 修改默认对齐数 4. 结构体传参4. 结构体实现位段5. 位段使用的注意事项 1. 结构体类型的声明和初始化 结构体在使用之前都要对其类型进行声明&#xff0c;关键字是struct&…

15分钟学 Python 第36天 :Python 爬虫入门(二)

Python 爬虫入门&#xff1a;环境准备 在进行Python爬虫的学习和实践之前&#xff0c;首先需要准备好合适的开发环境。本节将详细介绍Python环境的安装、必要库的配置、以及常用工具的使用&#xff0c;为后续的爬虫编写奠定坚实的基础。 1. 环境准备概述 1.1 为什么环境准备…

mp4转gif在线转换怎么转?7个视频转动图方法不容错过!(超简单)

mp4转gif在线转换怎么转&#xff1f;如今&#xff0c;将mp4视频转换为gif动图格式&#xff0c;满足了人们对易于分享和网络传播内容的需求。与mp4视频相比&#xff0c;gif动图文件体积相对较小&#xff0c;几乎所有网络平台都支持这种格式&#xff0c;无需额外安装插件或软件。…

CSID-GAN:基于生成对抗网络的定制风格室内平面设计框架论文阅读

CSID-GAN: A Customized Style Interior Floor Plan Design Framework Based on Generative Adversarial Network 摘要前言II. CSID-GAN METHODA. Overall FrameworkB. Algorithm and Loss Function III. DATASETS AND EVALUATION METRICSA. DatasetsB. Evaluation Metrics IV.…

信息安全工程师(34)访问控制模型

前言 访问控制模型是实现访问控制的基础&#xff0c;不同的访问控制模型提供了不同的访问控制策略和机制&#xff0c;以适应不同的安全需求。 一、自主访问控制模型&#xff08;DAC&#xff09; 定义&#xff1a;指资源的所有者有权决定谁可以访问其资源以及访问的方式。资源的…

如何实现事件流操作

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了通道相关的内容,本章回中将介绍StreamProvider组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stream是经常使用的组件,对该组件的监听可void main() {///让状态栏和程序的appBar融为一体…

macos安装mongodb

文章目录 说明安装和配置安装mongodb配置PATH变量 验证日志及数据存放目录 mac启动和关闭mongodb后台启动失败问题mongodb-compass(GUI) 说明 Homebrew core 列表目前已经将 MongoDB 移除,不再为其提供支持。但是使用国内镜像的brew还是可以安装的&#xff01;这里直接从官网下…

使用 Python 代码连接 PostgreSQL

Python 是一个功能非常强大的编程语言&#xff0c;尤其在与数据库交互时&#xff0c;提供了丰富的解决方案。在实际项目中&#xff0c;我们经常需要通过 Python 连接并操作数据库。为了简化这种操作&#xff0c;ORM&#xff08;对象关系映射&#xff09;框架提供了便利。ORM 能…

aws(学习笔记第一课) AWS CLI,创建ec2 server以及drawio进行aws画图

aws(学习笔记第一课) 使用AWS CLI 学习内容&#xff1a; 使用AWS CLI配置密钥对创建ec2 server使用drawio&#xff08;vscode插件&#xff09;进行AWS的画图 1. 使用AWS CLI 注册AWS账号 AWS是通用的云计算平台&#xff0c;可以提供ec2&#xff0c;vpc&#xff0c;SNS以及clo…

灵足时代:具身智能核心部件的新秀崛起——解析数千万元天使轮融资

在智能科技日新月异的今天,具身智能作为连接物理世界与数字世界的重要桥梁,正逐步成为科技创新的前沿阵地。近日,具身智能核心部件领域的新锐公司——“灵足时代”宣布完成数千万元天使轮融资,这一消息无疑为行业内外带来了强烈的震撼与期待。本轮融资由雅瑞智友科学家基金…

多用户网页聊天室(测试报告)

一、项目背景 随着现代互联网的快速发展&#xff0c;实时通信系统&#xff08;如聊天应用&#xff09;已成为人们日常交流的重要工具。多用户网页聊天室项目旨在为用户提供一个基于Web的实时聊天平台&#xff0c;支持用户之间的即时通信、好友管理和历史消息记录查看。为了提升…

ModuleNotFoundError: No module named ‘package‘

报错&#xff1a; Traceback (most recent call last): File “”, line 198, in run_module_as_main File “”, line 88, in run_code File "D:\python\helloworld.venv\Scripts\pip.exe_main.py", line 4, in File "D:\python\helloworld.venv\Lib\site-pac…

3分钟学会下载 blender

1. blender简介 Blender是一款开源的3D创作套件&#xff0c;它由Blender Foundation维护&#xff0c;并得到了全球志愿者和专业开发者的支持。Blender广泛应用于3D模型的制作、动画、渲染、视频编辑、游戏创建、模拟、 composting以及3D打印等多个领域。 功能特点&#xff1a…

Gitlab flow工作流

Gitlab flow Gitlab flow 是 Git flow 与 Github flow 的综合。它吸取了两者的优点&#xff0c;既有适应不同开发环境的弹性&#xff0c;又有单一主分支的简单和便利。它是 Gitlab.com 推荐的做法。 1 上游优先 Gitlab flow 的最大原则叫做"上游优先"&#xff08;…

【网络篇】计算机网络——应用层详述(笔记)

目录 一、应用层协议原理 1. 进入应用层 2. 网络应用程序体系结构 &#xff08;1&#xff09;客户-服务器体系结构&#xff08;client-server architecture&#xff09; &#xff08;2&#xff09; P2P 体系结构&#xff08;P2P architecture&#xff09; 3. 进程间通讯 …

2024/10/5 数据结构打卡

对两个长度为n的升序序列A和B的元素按由小到大的顺序依次访问&#xff0c;这里访问的 含义只是比较序列中两个元素的大小&#xff0c;并不实现两个序列的合并&#xff0c;因此空间复杂度为 O(1)。按照 上述规则访问到第n个元素时&#xff0c;这个元素即为两个序列A和B的中位数。…