二叉树常见面试题(进阶)

2023-11-14

一、常见题型

1. 求两个节点的最近公共祖先;

2. 求二叉树中最远的两个节点的距离;

3. 由前序遍历和中序遍历重建二叉树(如:前序序列:1 2 3 4 5 6 - 中序序列 :3 2 4 1 6 5);

4. 判断一棵树是否是完全二叉树 ;

5. 将二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向;

6.求二叉树的宽度;

7. 判断一棵二叉树是否是平衡二叉树;

8.判断一颗二叉树是否是另一颗树的子树。

二、解题思路分析

1.两个节点的最近公共祖先

求两个节点的最近公共祖先可分为三种情况,分别为:

(1)搜索二叉树,根据搜索二叉树的性质,左子树的所有节点比根节点小,右子树的所有节点比跟节点大。


如果两个节点都比根节点小,则递归左子树 ;
如果两个节点都比跟节点大,则递归右子树 ;
否则,两个节点一个在左子树,一个在右子树,则当前节点就是最近公共祖先节点。

 1 Node* GetAncestor(Node* root, Node* x1, Node* x2)//1.该二叉树为搜索二叉树
 2         {
 3             assert(x1 && x2);
 4             if (x1->_data <= root->_data && x2->_data <= root->_data)
 5             {
 6                 return GetAncestor(root->_left, x1, x2);//两个节都小于根节点,最近公共祖先在左子树中
 7             }
 8             else if (x1->_data > root->_data && x2->_data > root->_data)
 9             {
10                 return GetAncestor(root->_right, x1, x2);//两个节都大于根节点,最近公共祖先在左子树中
11             }
12             else
13                 return root;  //一个在左子树,一个在右子树,找到公共祖先
14 
15         }

(2)三叉链,二叉树节点有指向父节点的指针。首先给出node1的父节点node1->_parent,然后将node1的所有父节点依次和node2->parent作比较,如果发现两个节点相等,则该节点就是最近公共祖先,直接将其返回。如果没找到相等节点,则将node2的所有父节点依次和node1->_parent->_parent作比较......直到node1->_parent==NULL。代码如下:

 1     struct BinaryNode   //节点的结构
 2  {  3 BinaryNode* _left;  4 BinaryNode* _right;  5 BinaryNode* _parent;  6 int _data;  7  8 BinaryNode(const int& data)  9  :_data(data) 10  , _left(NULL) 11  , _right(NULL) 12  , _parent(NULL) 13  {} 14 }; 
 1   Node * GetLastCommonAncestor(Node * root, Node * node1, Node * node2)  
 2     {  
 3         Node * temp;  
 4         while (node1 != NULL)  
 5         {  
 6             node1 = node1->_parent;  
 7             temp = node2;  
 8             while (temp != NULL)  
 9             {  
10                 if (node1 == temp->_parent)  
11                     return node1;  
12                 temp = temp->_parent;  
13             }  
14         }  
15     }  

该算法时间复杂度为O(n^2),可用另一种O(n)的算法:

给定的两个节点都含有父节点,因此,可将这两个节点看做是两个链表的头结点,将求两个节点的最近公共祖先节点转化为求两链表的交点,这两个链表的尾节点都是根节点。

 1     int Hight(BinaryNode* root, BinaryNode* node)  
 2     {  
 3         int len = 0;  
 4         for (; node != NULL; node = node->_parent)  
 5             len++;  
 6       
 7         return len;  
 8     }  
 9     BinaryNode* GetLastCommonAncestor(BinaryNode* root, BinaryNode* node1, BinaryNode* node2)  
10     {  
11       
12         if (root == NULL || node1 == NULL || node2==NULL)  
13             return NULL;  
14       
15         int len1 = Hight(root,node1);  
16         int len2 = Hight(root,node2);  
17               
19         for (; len1 > len2; len1--)  
20             node1 = node1->_parent;  
21         for (; len2 > len1; len2--)  
22             node2 = node2->_parent;  
23       
24         while (node1 && node2 && node1 != node2)  
25         {  
26             node1 = node1->_parent;  
27             node2 = node2->_parent;  
28         }  
29           
30         if (node1 == node2)  
31             return node1;  
32         else  
33             return NULL;  
34     }  

(3)普通二叉树,这种情况可采用与搜索二叉树类似的解法

 从根节点开始遍历,如果node1和node2中的任一个和root匹配,那么与root匹配的节点就是最低公共祖先。 如果都不匹配,则分别递归左、右子树,如果有一个 节点出现在左子树,并且另一个节点出现在右子树,则root就是最低公共祖先.  如果两个节点都出现在左子树,则说明最低公共祖先在左子树中,否则在右子树。

 1 Node* GetAncestor(Node* root, Node* x1, Node* x2)
 2         {
 3             assert(x1 && x2);
 4             if (root == NULL) {
 5                 return NULL;
 6             }
 7             if (root == x1 || root == x2) //如果两个节点是父子关系,其中的一个节点为公共祖先
 8             {
 9                 return root;
10             }
11             bool x1inleft, x2inleft, x1inright, x2inright;
12             x1inleft = JudgeNode(root->_left, x1);  //判断x1是否在左子树
13             x1inright = JudgeNode(root->_right x1);  //判断x1是否在右子树
14             assert(x1inleft || x1inright);  //至少有一个为真
15             x2inleft = JudgeNode(root->_left, x2);  //判断x2是否在左子树
16             x2inright = JudgeNode(root->_right, x2);  //判断x2是否在右子树
17             assert(x2inleft || x2inright);  //至少有一个为真
18             if ((x1inleft && x2inright) || (x1inright && x2inright))
19             {
20                 return root;  //一个在左子树,一个在右子树,找到公共祖先
21             }
22             else if (x1inleft && x2inleft)  //两个节都在左子树中,最近公共祖先在左子树中
23             {
24                 return GetAncestor(root->_left, x1, x2);
25             }
26             else {  //两个节都在右子树中,最近公共祖先在右子树中
27                 return GetAncestor(root->_right, x1, x2);
28             }
29         }

上述方法时间复杂度为O(N^2),下面的方法时间复杂度为O(N),但是需要额外的空间来存储路径。

1) 找到从根到node1的路径,并存储在一个向量或数组中。
2)找到从根到node2的路径,并存储在一个向量或数组中。
3) 遍历这两条路径,直到遇到一个不同的节点,则前面的那个即为最低公共祖先.

 

 1         bool GetNodePaths(Node* root, Node* node, stack<Node *>& s)
 2         {
 3             if (root == NULL)
 4             {
 5                 return false;
 6             }
 7             s.push(root);
 8             if (root == node)
 9             {
10                 return true;
11             }
12             bool inleft = GetNodePaths(root->_left, node, s);
13             if (inleft)
14             {
15                 return true;
16             }
17             bool inright = GetNodePaths(root->_right, node, s);
18             if (inright)
19             {
20                 return true;
21             }
22             s.pop();
23             return false;
24         }
25         Node* GetAncestor(Node* root, Node* x1, Node* x2);
26         {
27             assert(x1 && x2);
28             stack<Node*> paths1, paths2;
29             if (!GetNodePaths(root->_left, x1, paths1) || !GetNodePaths(root->_right, x2, paths2))
30             {
31                 return NULL;
32             }
else{
           while(paths1.size()>paths2.size()){
              paths1.pop();
           }
           while(paths1.size()<paths2.size()){
              paths2.pop();
           }

           while(!paths1.empty() && !paths2.empty() && paths1.top()!=paths2.top()){
              if(paths1.top()==paths2.top())
                return paths1.top();
              paths1.pop();
              paths2.pop();
           }
         }
         return NULL;
33 }

2.最远的两个节点的距离

 第一种情况最远的两个节点的距离为它们到根节点的路径长度之和,又有可能距离最远的两个节点之间的路径不经过根节点,如图所示:

所以不要考虑不全,直接用两个子树的的高度相加来表示最远的两个节点的距离。有两种方法求解:

还是要借助两个子树的高度求解,但是要递归整棵树,如果子树中出现第二种情况要更新最大距离,时间复杂度为O(N^2)。

 1     //求二叉树中最远的两个节点的距离
 2     size_t MaxLen()
 3     {
 4         size_t maxlen = 0;
 5         _MaxLen(_root, maxlen);
 6         return maxlen;
 7     }
 8     void _MaxLen(Node* root, size_t maxlen)  //O(N^2)
 9     {
10         if (root == NULL)
11         {
12             return 0;
13         }
14         int leftdepth = Depth(root->_left);  
15         int rightdepth = Depth(root->_right);
16         if (leftdepth + rightdepth > maxlen)
17         {
18             maxlen = leftdepth + rightdepth;
19         }
20         _MaxLen(root->_left, maxlen);
21         _MaxLen(root->_right, maxlen);
22     }

另一种时间复杂度为O(N)的解法:

 1     size_t _MaxLen(Node* root, size_t maxlen)  //O(N)
 2     {
 3         if (root == NULL)
 4         {
 5             return;
 6         }
 7         size_t left = _MaxLen(root->_left, maxlen);
 8         size_t right = _MaxLen(root->_right, maxlen);
 9         if (right+left>maxlen)
10         {
11             maxlen = right + left;
12         }
13         return left > right ? left + 1 : right + 1;
14     }

3. 前序遍历和中序遍历重建二叉树

这个题是要用一颗二叉树的前序遍历序列和中序遍历序列,如:前序序列:1 2 3 4 5 6 - 中序序列 :3 2 4 1 6 5,来重新构建二叉树。可以利用前序序列和中序序列中根节点的位置特性作为重建依据。图示解析过程如下:

创建右子树的方法与左子树的方法完全相同。当 prev 遍历完前序序列,即二叉树创建完成。代码如下:

 1 //由前序遍历和中序遍历重建二叉树(如:前序序列:1 2 3 4 5 6 - 中序序列 :3 2 4 1 6 5)
 2         Node* RebulidTree(char* prev, char* inbgein, char* inend)
 3         {
 4             assert(prev && inbgein && inend);
 5             if (inbgein > inend || prev == '\0')
 6             {
 7                 return NULL;
 8             }
 9             Node* root = new Node(*prev);  //先创建根节点
10             char* div = inbgein;  //让div查找根节点
11             while (div <= inend) {
12                 if (*div == *prev)
13                 {
14                     if (inbgein <= div -1)
15                     {
16                         root->_left = RebulidTree(++prev, inbgein, div - 1);//递归创建左子树
17                     }
18                     else {
19                         root->_left = NULL;
20                     }
21                     if (div + 1 <= inend)
22                     {
23                         root->_right = RebulidTree(++prev, div + 1, inend);//递归创建右子树
24                     }
25                     else {
26                         root->_right = NULL;
27                     }
28                     break;
29                 }
30                 ++div;
31             }
32             return root;
33         }

4. 判断一棵树是否是完全二叉树

完全二叉树: 前n-1层都是满的,第n层如有空缺,则是缺在右边,即第n层的最右边的节点,它的左边是满的,右边是空的。

这是一个层序遍历非递归法的变型题,同样要借助额外空间来临时存储节点。按照层序遍历二叉树,找到第一个只有非满结点(这个节点只有两种情况,孩子为空或者只有左没有右),如果之后的节点还有非满结点,则不是。

 1     bool IsComplateTree(Node* root)
 2     {
 3         queue<Node*> q;
 4         if (root)
 5         {
 6             q.push(root);  //先将节点压入队列中
 7         }
 8         //这里给一个tag是标记是否出现非满节点
 9         bool tag = true;
10         while (!q.empty())
11         {
12             Node* front = q.front();  
13             q.pop();
14             //如果已经出现过非满结点,则后面再出现有孩子的结点则一定不是完全二叉树。
15             if (front->_left)
16             {
17                 if (tag == false)
18                 {
19                     return false;
20                 }
21                 q.push(front->_left);
22             }
23             else {
24                 tag = false;
25             }
26             if (front->_right)
27             {
28                 if (tag == false)
29                 {
30                     return false;
31                 }
32                 q.push(front->_right);
33             }
34             else {
35                 tag = false;
36             }
37         }
38         return true;
39     }

第二种思路:将所有的结点全部押入队列中,每次判断队列的头如果队列头为空了则跳出循环,如果此后队列中还有元素则不是完全二叉树。

 1 bool IsCompleteTree(BinaryTreeNode *pRoot)
 2 {
 3          if(pRoot == NULL)
 4                return false;
 5 
 6           queue<BinaryTreeNode*> q;
 7           q.push(pRoot);
 8           BinaryTreeNode* pCur = q.front();
 9           while(pCur != NULL)
10           {
11                q.pop();
12                q.push(pCur -> left);
13                q.push(pCur -> right);
14                pCur = q.front();
15           }
16 
17           q.pop();//把空pop出来
18           //因为以经有一个空了,所以只要头不为空就不是完全二叉树
19           while(! q.empty())
20           {
21                if(q.front() != NULL)
22                     return false;
23                q.pop();
24           }
25           return true;
26 }

5. 将二叉搜索树转换成一个排序的双向链表

与二叉树的线索花化雷同

 1     void _ToList(Node* cur, Node*& prev)
 2     {
 3         if (cur == NULL)
 4             return;
 5 
 6         _ToList(cur->_left, prev);
 7         // 
 8         cur->_left = prev;
 9         if(prev)
10             prev->_right = cur;
11 
12         prev = cur;
13 
14         _ToList(cur->_right, prev);
15     }
16 
17     Node* ToList(Node* root)
18     {
19         Node* prev = NULL;
20         _ToList(root, prev);
21 
22         Node* head = root;
23         while (head && head->_left)
24         {
25             head = head->_left;
26         }
27 
28         return head;
29     }

6.求二叉树的宽度

所谓二叉树的宽度是指:二叉树各层节点个数的最大值。

我们知道层序遍历二叉树是使用 queue 来实现的:每次打印一个节点之后,如果存在左右子树,则把左右子树压入 queue,那么此时的队列中可能既包含当前层的节点,也包含下一层的节点。

而我们要求的是对于特定某一层的节点的个数,因此我们需要从头结点开始,记录每一层的个数,对于当前层的每一个节点,在弹出自身之后把其左右子树压入 queue,当把当前层全部弹出队列之后,在队列中剩下的就是下一层的节点。然后比较队列的size和之前得到的maxWidth,取最大值即为队列的宽度。最终队列为空,得到的maxWidth就是二叉树的宽度!

 1     int Width(Node* root)
 2     {
 3         queue<Node*> q;
 4         if (root)
 5             q.push(root);
 6         int maxwidth = 1;
 7         while (!q.empty())    
 8         {
 9             int length = q.size();
10             while (length-- > 0)    
11             {
12                 Node* front = q.front();
13                 q.pop();
14                 if (front->_left)
15                 {
16                     q.push(front->_left);
17                 }
18                 if (front->_right)
19                 {
20                     q.push(front->_right);
21                 }
22             }
23             maxwidth = maxwidth > q.size() ? maxwidth : q.size();
24         }
25         return maxwidth;
26     }

7. 二叉树是否是平衡二叉树

二叉树中每一个节点的左右子树高度之差均小于2即为平衡二叉树。那么当一颗二叉树的所有子树都是平衡二叉树时,它本身必定为平衡二叉树,用此思想可递归判断二叉树是否是平衡二叉树。代码如下:

 1     //--判断一棵二叉树是否是平衡二叉树
 2     bool IsBalance(Node* root)  //O(N^2)
 3     {
 4         if (root == NULL)
 5         {
 6             return false;
 7         }
 8         int left = Depth(root->_left);
 9         int right = Depth(root->_right);  
10         return abs(right - left) < 2 && IsBalance(root->_left) && IsBalance(root->_right);
11     }

这种方法借助左右的高度比较来确定是否为二叉树,需多次遍历二叉树,时间复杂度为O(N^2)。下面是一种O(N)的算法:

 1     bool IsBalance(Node* root, int& depth)  //O(N)
 2     {
 3         if (root == NULL)
 4         {
 5             depth = 0;
 6             return true;
 7         }
 8         int leftdepth = 0;
 9         if (IsBalance(root->_left, leftdepth) == false)
10         {
11             return false;
12         }
13         int rightdepth = 0;
14         if (IsBalance(root->_right, rightdepth) == false)
15         {
16             return false;
17         }
18         depth = rightdepth > leftdepth ? rightdepth + 1 : leftdepth + 1;
19         return abs(leftdepth - rightdepth) < 2;
20     }

 8.二叉树是否为另一颗树的子树

判断一颗二叉树是否是另一颗树的子树。

 先在找二叉树里找根节点,找到之后判断后续的节点是否相等,如果相等,则为子树。

 1     bool JudgeNextTree(Node* next, Node* child) //两棵树的起始节点的值已经相等,在判断其他节点是否相等
 2     {
 3         if (child == NULL)
 4         {
 5             return true;
 6         }
 7         if (next == NULL)
 8         {
 9             return false;
10         }
11         if (next->_data == child->_data)    //
12         {
13             return JudgeNextTree(next->_left, child->_left) && JudgeNextTree(next->_right, child->_right);
14         }
15         else {
16             return false;  //如果左右孩子都相等,则是子树,否则不是
17         }
18     }
19     bool JudgeTree(Node* parent, Node* child) //判断child是否为parent的子树
20     {
21         if (child == NULL) //空树是任何树的子树
22         {
23             return true;
24         }
25         if (parent == NULL)  //空树没有除空树的任何子树
26         {
27             return false;
28         }
29         if (parent->_data == child->_data)  //当前节点与要查找子树的根节点相同时
30         {
31             return JudgeNextTree(parent, child);  //从相等节点开始判断是否为子树
32         }
33         else if (JudgeTree(parent->_left, child->_left) == true)  //判断当前节点的左子树是否与要查找子树的根节点相同
34         {
35             return true;
36         }
37         else {
38             return JudgeTree(parent->_right, child->_right);  //判断当前节点的右子树是否与要查找子树的根节点相同
39         }
40     }

 

转载于:https://www.cnblogs.com/33debug/p/7252371.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树常见面试题(进阶) 的相关文章

  • Mysql 数据库

    数据库基础 1 什么是数据库 用来存储数据 数据库可在硬盘及内存中存储数据 数据库与文件存储数据的区别 数据库本质也是通过文件来存储数据 数据库的概念就是系统的管理存储数据的文件 数据库介绍 本质就是存储数据的C S架构的socket套接字
  • netty handler的执行顺序(3)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 今天解决2个问题 1 handler在pipeline当中究竟是如何存储的 2 在遍历handler的过程中 会根据event的不同 调用不同的handler 这一点是如何
  • Sort List

    Sort a linked list in O n log n time using constant space complexity 题目要求用 O n log n 的时间复杂度和常数的空间复杂度来进行链表排序 O nlogn 的排序算
  • 一文弄懂循环链表、双向链表、静态链表

    循环链表 双向链表 静态链表 三遍定律 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 1 循环链表 将单链表中终端结点的指针端由空指针改
  • JavaScript实现数据结构 -- 链表

    文章目录 链表 链表的特点 链表和数组的区别 JS模拟链表 遍历链表 插入节点 删除节点 链表应用 删除链表中的节点 leetcode 237 思路 代码 反转链表 leetcode 206 思路 代码 链表 链表和数组一样是有多个元素组成
  • 常用的十种算法--马踏棋盘算法

    1 马踏棋盘算法介绍 马踏棋盘算法也被称为骑士周游问题 将马随机放在国际象棋的 8 8 棋盘 Board 0 7 0 7 的某个方格中 马按走棋规则 马走日字 进行移动 要求每个方格只进入一次 走遍棋盘上全部 64 个方格 2 马踏棋盘算法
  • 数据结构与算法学习总结(六)——字符串的模式匹配算法

    基本概念 字符串是一种特殊的线性表 即元素都是 字符 的线性表 字符是组成字符串的基本单位 字符的取值依赖于字符集 例如二进制的字符集为0 1 则取值只能为 0 1 再比如英语语言 则包括26个字母外加标点符号 例如 abcde 就是一个字
  • 递归算法中的时间复杂度分析

    对于一种算法的时间复杂度分析还是特别重要的 在一些非递归算法中 我们仅仅看运算次数最多的那一行代码可能执行多少次就可以 实际就是看在循环中变量的变化 但是对于递归算法中该怎么分析呢 下面介绍几种递归函数中的算法时间复杂度分析的方法 0 递推
  • 『Python基础-15』递归函数 Recursion Function

    什么是递归函数 一种计算过程 如果其中每一步都要用到前一步或前几步的结果 称为递归的 用递归过程定义的函数 称为递归函数 例如连加 连乘及阶乘等 凡是递归的函数 都是可计算的 即能行的 递归就是一个函数在它的函数体内调用它自身 编程语言中的
  • 以太坊系列之十五: 以太坊数据库

    以太坊数据库中都存了什么 以太坊使用的数据库是一个NOSQL数据库 是谷歌提供的开源数据leveldb 这里尝试通过分析以太坊数据库存储了什么来分析以太坊可能为我们提供哪些关于区块链的API 存储内容 NOSQL是一个key value数据
  • 图 - Java实现无向带权图的邻接矩阵表示法

    图 Java实现无向带权图的邻接矩阵表示法 1 图 1 1 图的介绍 图 Graph 是一种复杂的非线性表结构 图中的元素我们就叫做顶点 vertex 图中的一个顶点可以与任意其他顶点建立连接关系 我们把这种建立的关系叫做边 edge 跟顶
  • 数据结构——计算节点个数和二叉树高度(C语言版)

    摘自 数据结构 计算节点个数和二叉树高度 C语言版 作者 正弦定理 发布时间 2020 12 12 23 27 09 网址 https blog csdn net chinesekobe article details 111086664
  • 用指针访问一维数组

    文章目录 顺序查找 数组方式实现 指针实现方式 对一位数组元素的访问有三种方式 指针变量的关系运算 引例 数组实现方式 主函数 指针实现方式 主函数 一维数组作为函数的参数 实际应用 顺序查找 要求用指针实现 在整数集合r中顺序查找与给定值
  • 数理统计知识整理——回归分析与方差分析

    题记 时值我的北科研究生第一年下 选学 统计优化 课程 备考促学 成此笔记 以谨记 1 线性回归 1 1 原理分析 要研究最大积雪深度x与灌溉面积y之间的关系 测试得到近10年的数据如下表 使用线性回归的方法可以估计x与y之间的线性关系 线
  • 基数排序代码实现

    详情请看排序总结 传送门 https blog csdn net m0 52711790 article details 121914543 基数排序的知识点我就不贴出来 相信都能搜到对应概念解释 下面就直接上代码 代码解释其实也很清晰了
  • Leetcode2661. 找出叠涂元素

    Every day a Leetcode 题目来源 2661 找出叠涂元素 解法1 哈希 题目很绕 理解题意后就很简单 由于矩阵 mat 中每一个元素都不同 并且都在数组 arr 中 所以首先我们用一个哈希表 hash 来存储 mat 中每
  • Leetcode1094. 拼车

    Every day a Leetcode 题目来源 1094 拼车 解法1 差分数组 对于本题 设 a i 表示车行驶到位置 i 时车上的人数 我们需要判断是否所有 a i 都不超过 capacity trips i 相当于把 a 中下标从
  • 牛客剑指offer刷题其他算法篇

    文章目录 构建乘积数组 题目 思路 代码实现 第一个只出现一次的字符
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数

随机推荐

  • JS 传各种文件到后端

    一个前端上传文件按钮功
  • 伯努利分布的最大似然估计

    前言 昨天晚上参加阿里巴巴的实习面试 各种被虐 面试了将近90分钟 才做了3个题 加上项目的介绍 在机器学习方面 问到了一个伯努利分布的最大似然估计的推导 想到逻辑回归的推导就是利用最大似然估计 然后就套用了其推导过程 可能前面被说的有点迷
  • python之js解密_python中的RSA加密和JS中的解密

    我是密码学的全新人物 我想从服务器端生成RSA密钥对 并将其发送给所有客户端 浏览器 但在此之前 我只是通过加密python中的数据并通过pubnub发送到index html文件并尝试在JavaScript中解密来测试场景 问题是当我做加
  • Redis——Windows安装

    本篇只谈安装 后续会深入讲解Redis 比如它的内存管理 快照 订阅等待 针对不同的用户 Redis有Windows和Linux两种环境安装 官网上下的是Statble版是Linux 大家一定要注意 由于本人做本地端 所以以下谈的是Wind
  • SpringBean生命周期&扩展接口&简化配置

    目录 1 生命周期简图 2 扩展接口介绍 BeanFactoryPostProcessor接口 Aware接口 BeanPostProcessor接口 InitializingBean接口 DisposableBean接口 3 spring
  • kafka 集成SpringBoot

    目录 一 Kraft模式 配置 集群启动停止脚本 二 集成SpringBoot 资源配置 生产者 消费者 三 API 依赖 yml格式配置文件 properties格式配置文件 一 Kraft模式 kafka 2 8 0后新特性 2 8 0
  • 【Monkey测试】手机app测试性能测试,Monkey测试详解(全)

    目录 导读 前言 一 Monkey工具 二 Monkey的优劣 三 Monkey 命令 四 Monkey结果分析 五 Monkey详细 六 Monkey用来做什么 七 Monkey程序介绍 八 Monkey命令基本参数 九 Event pe
  • 无线网络安全——1、WiFi安全基础知识

    0x01 WiFi简介 智能手机的快速发展已将近十年左右 较之旧款的非智能手机 最大的区别应该是在于其强大的上网功能 在4G技术已经普及的今天 无奈国内的电信运营商们把移动联网流量的价格抬的让人无法深爱 加之家庭用户和企业用户对于物理网络线
  • Linux基础命令-du查看文件的大小

    文章目录 du 命令介绍 语法格式 基本参数 参考实例 1 以人类可读形式显示指定的文件大小 2 显示当前目录下所有文件大小 3 只显示目录的大小 4 显示根下哪个目录文件最大 5 显示所有文件的大小 6 只显示目录下的文件 不显示目录下的
  • 2017 408选择题错题

    2017 408选择题错题 1 下列函数的时间复杂度是 int func int n int i 0 sum 0 while sum lt n sum i return i sum i 等于 sum sum i sum 0 i 0 sum
  • 错误笔记: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) E: Unable ...

    alexander alexander virtual machine sudo apt get install y httpdE Could not get lock var lib dpkg lock open 11 Resource
  • 5.基本统计方法-连续性变量的组间比较

    目录 1 两样本的定量变量的假设检验 1 1 单样本t检验 1 2 两独立样本t检验 1 3 配对样本t检验 1 4 正态性检验和方差齐性检验 2 多样本定量变量的假设检验 2 1 基本知识 2 2 单因素方差分析 2 3 单因素的协方差分
  • vs code 安装插件出现XHR error 解决办法

    在给vscode安装颜色主题时 突然发现出现错误XHR failed 插件安装失败 后来想起可能是因为修改过系统时间 果然在恢复自动设置时间之后 插件就可以安装成功了
  • Qt+数据库学习笔记(一)win10+Qt5.12.12+VS2019_x64编译mysql8.0驱动插件

    前言 因项目需要 需要使用Qt连接mysql数据库 笔者上次使用此数据库 已过去很久了 当前版本都发生了很大的变化 笔者在此记录下本次编译过程 一 安装mysql8 0 注 若读者使用的是win7系统 请提前安装 net4 5 否则可能无法
  • java 图片 背景 透明

    package com picture import java awt Graphics2D import java awt image BufferedImage import java io File import java io IO
  • Acwing算法—动态规划

    目录 数字三角形模型 AcWing 898 数字三角形 AcWing 1015 摘花生 AcWing 1018 最低通行费 AcWing 1027 方格取数 AcWing 275 传纸条 最长上升子序列模型 AcWing 895 最长上升子
  • nRF52832 — 串口BLE例程逐行解析【转载】

    原文链接 http blog csdn net u011034150 article details 50617686 转载文章 若有不妥 通知后我会立即删除 本讲逐行代码解析官方串口BLE例程demo 主要分一下几个部分 1 Main函数
  • STM32开发——YModem文件传输协议详解与实现

    STM32开发 YModem文件传输协议详解与实现 在单片机的应用开发中 文件的传输是不可或缺的一部分 而在传输文件时 为了保证传输的稳定性和可靠性 采用一种可靠性高的传输协议是至关重要的 本文将介绍一种常见的文件传输协议 YModem 并
  • java实现数据库备份与恢复

    前言 为了应对项目中数据库突然奔溃 导致丢失数据 这时可以通过代码实现数据库的定时备份与恢复 即使数据库宕机了 我们也可以将之前备份好的数据信息还原到数据库 通过java代码实现数据库的备份与恢复 其实就是通过java代码操作命令行 那么如
  • 二叉树常见面试题(进阶)

    一 常见题型 1 求两个节点的最近公共祖先 2 求二叉树中最远的两个节点的距离 3 由前序遍历和中序遍历重建二叉树 如 前序序列 1 2 3 4 5 6 中序序列 3 2 4 1 6 5 4 判断一棵树是否是完全二叉树 5 将二叉搜索树转换