二叉树常见面试题(进阶) – 滴巴戈

一、通俗的题型

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             断言(X1) && X2);
 4if (x1->_data <= root->_data && x2->_data <= root->档案)
 5            {
 6return GetAncestor(根)->_left, x1, X2);//这两个局部以内根杂种。,左子树说得中肯重行协同先人 7            }
 8elseif (x1->_data > root->_data && x2->_data > root->档案)
 9            {
10return GetAncestor(根)->_right, x1, X2);//这两个局部大于根杂种。,左子树说得中肯重行协同先人11            }
12else13return root;  //左子树说得中肯独一,右子树说得中肯独一,寻觅协同先人1415         }

(2)三叉神经链,二叉树杂种有蠲父杂种的方针。率先,产生NODE1的父杂种NODE1->父父杂种。,尔后将NoDE1的各种的父杂种与NoDE2->父杂种停止相对地。,以防显示证据两个杂种相当,很杂种是重行的协同先人。,直率的又来。以防不注意找到相当的杂种,则将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& 档案)  
 9             :_data(档案)  
10             , 左(空)  
11             , 右(空)  
12             , 父(空)  
13         {}  
14     };  
 1   Node * GetLastCommonAncestor(Node * root, Node * node1, Node * node2)  
 2    {  
 3         Node * temp;  
 4while (node1 != 空)  
 5        {  
 6             node1 = node1->_parent;  
 7             temp = node2;  
 8while (体温) != 空)  
 9            {  
10if (node1 == temp->父亲)  
11return node1;  
12                 temp = temp->_parent;  
13            }  
14        }  
15     }  

算法的工夫复杂性为O(n ^ 2)。,O(n)的另类的算法:

考虑到的两个杂种具有父杂种,故,这两个杂种可以敬重是两个链表的头杂种。,将两个杂种的重行公共先人杂种转变为求两链表的交点,两个链表的尾随者杂种都是根杂种。。

 1int Hight(BinaryNode* root, BinaryNode* 杂种)  
 2    {  
 3int len = 0;  
 4for (; node != NULL; node = node->父亲)  
 5             len++;  
 6 7return len;  
 8    }  
 9     BinaryNode* GetLastCommonAncestor(BinaryNode* root, BinaryNode* node1, BinaryNode* node2)  
10    {  
1112if (根) == NULL || node1 == NULL || node2==空)  
13return NULL;  
1415int len1 = Hight(根),node1);  
16int len2 = Hight(根),node2);  
1719for (; len1 > len2; len1--)  
20             node1 = node1->_parent;  
21for (; len2 > len1; len2--)  
22             node2 = node2->_parent;  
2324while (node1 && node2 && node1 != node2)  
25        {  
26             node1 = node1->_parent;  
27             node2 = node2->_parent;  
28        }  
2930if (node1 == node2)  
31return node1;  
32else33return NULL;  
34     }  

(3)普通二叉树,这种制约可采用与搜索二叉树类似物的处理

从根杂种开端遍历,以防NoDE1和NoDE2说得中肯无论哪一个独一与根婚配,与根婚配的杂种是最小的的协同先人。。 以防不婚配,尔后循环左、右子树,以防有独一 杂种呈现时左子树中,另独一杂种呈现时右子树中,根是最小的的协同先人。 以防在左子树中呈现两个杂种,算是蠲,最小协同先人谎言左子树中。,不然在右子树中。

 1 Node* GetAncestor(Node* root, Node* x1, Node* X2)
 2        {
 3             断言(X1) && X2);
 4if (根) == 空) {
 5return NULL;
 6            }
 7if (根) == x1 || root == X2) //以防两个杂种是爷儿俩相干,在内地独一杂种是协同先人。 8            {
 9return root;
10            }
11bool x1inleft, x2inleft, x1inright, x2inright;
12             x1inleft = JudgeNode(根)->_left, X1)  //决定x1其说得中肯哪独一在左子树中13             x1inright = JudgeNode(根)->_right X1)  //决定x1其说得中肯哪独一在右子树中14             断言(X1)inleft || x1in右)  //反正有独一是真的15             x2inleft = JudgeNode(根)->_left, X2);  //决定x2其说得中肯哪独一在左子树中16             x2inright = JudgeNode(根)->_right, X2);  //决定x2其说得中肯哪独一在右子树中17             assert(x2inleft || x2in右)  //反正有独一是真的18if ((x1inleft && x2inright) || (x1inright && x2inright))
19            {
20return root;  //左子树说得中肯独一,右子树说得中肯独一,寻觅协同先人21            }
22elseif (x1inleft && x2in左)  //这两个局部在左子树中。,左子树说得中肯重行协同先人23            {
24return GetAncestor(根)->_left, x1, X2);
25            }
26else {  //这两个局部在右子树中。,右子树说得中肯重行协同先人27return GetAncestor(根)->_right, x1, X2);
28            }
29         }

前述的方法的工夫复杂性为O(n ^ 2)。,工夫复杂性的以下方法是O(n),早已必要额定的留空隙来储藏处路程。。

1) 找到从根到杂种1的路程,并储藏处在矢量或一大批中。
2)找到从根到杂种2的路程,并储藏处在矢量或一大批中。
3) 遍历这两条路程,直到尤指不期而遇差额的杂种,后头的独一是最小的的协同先人。

 

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

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

两个最远的杂种私下的间隔为2。

在第一种制约下,两个最远的杂种私下的间隔是SU。,也有能够从最远的DI私下的两个杂种私下的路程。,如图所示:

因而不要去想它。,直率的表现两个最远的杂种与间隔的间隔。有两种处理方法:

它依然必要经过两个子树的高音调的来处理。,只整个的树的循环,以防在子树中在居第二位的种制约,则最大间隔应该是UPD。,工夫复杂性为O(n ^ 2)。

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

工夫复杂性的另类的处理方案是O(n)。:

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

3. 前序遍历和中序遍历重行组装二叉树

很题是要用一颗二叉树的前序遍历序列和中序遍历序列,如:前序序列:1 2 3 4 5 6 – 中序序列 :3 2 4 1 6 5,来重行构成二叉树。咱们可以应用根杂种的臀部特点在前序SE中。。图解解析做事方法列举如下:

找到右子树的方法与。当 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             断言 && inbgein && inend);
 5if (inbgein > inend || prev == ''\0'')
 6            {
 7return NULL;
 8            }
 9             Node* root = new 杂种(*PRV)  //率先找到根杂种10char* div = inbgein;  //让div查找根杂种11while (DIV) <= inend) {
12if (*div == *前级)
13                {
14if (inbgein <= div -1)
15                    {
16                         root->_left = RebulidTree(++prev, inbgein, div - 1);//循环找到左子树17                    }
18else {
19                         root->_left = NULL;
20                    }
21if (DIV) + 1 <= inend)
22                    {
23                         root->_right = RebulidTree(++prev, div + 1, inend);//循环找到右子树24                    }
25else {
26                         root->_right = NULL;
27                    }
28break;
29                }
30                 ++div;
31            }
32return root;
33         }

4. 断定一棵树其说得中肯哪独一是完成或结束二叉树

完成或结束二叉树: 前n-1层满,以防在启动,则层N,它在正确掉了,n层最正确的杂种,左面是满的。,正确是空的。。

这是独苗圃序遍历非循环法的变型题,还必要应用额定的留空隙来储藏处杂种。。秉承层序遍历二叉树,查找第独一非完成或结束杂种(此杂种可是两个侦查),这孩子是空的,或许只剩不注意兴趣的。,以防后头的杂种有非满杂种,则过失。

 1bool IsComplateTree(Node* 根)
 2    {
 3         queue q;
 4if (根))
 5        {
 6             q.push(根));  //率先将杂种压入队列 7        }
 8//在在这里,以防加标签于出庭争端满杂种,则产生加标签于。 9bool tag = true;
10while (!())
11        {
12             Node* front = ();  
13            q.pop();
14//以防非满杂种早已呈现,则后头再呈存在孩子的使纠结则必然过失完成或结束二叉树。15if (舌前的)左)
16            {
17if (加标签于) == false)
18                {
19returnfalse;
20                }
21                 q.push(舌前的)左)
22            }
23else {
24                 tag = false;
25            }
26if (舌前的)右)
27            {
28if (加标签于) == false)
29                {
30returnfalse;
31                }
32                 q.push(舌前的)右)
33            }
34else {
35                 tag = false;
36            }
37        }
38returntrue;
39     }

居第二位的种思考方法:将各种的杂种相信队列中,无论何时咱们断定队列头时,以防队列头是空的,这么JUM,以防尔后队列中更元素则过失完成或结束二叉树。

 1bool IsCompleteTree(BinaryTreeNode *普罗特)
 2{
 3if(普罗特 == 空)
 4returnfalse;
 5 6           queue q;
 7          q.push(普罗特);
 8           BinaryTreeNode* pCur = ();
 9while(pCUR) != 空)
10          {
11               q.pop();
12                q.push(pCUR) -> 左)
13                q.push(pCUR) -> 右)
14                pCur = ();
15          }
1617           q.pop();//滚出空无所有的防喷器
18//因有独一空的。,因而既然头不为空就过失完成或结束二叉树19while(! ())
20          {
21if(() != 空)
22returnfalse;
23               q.pop();
24          }
25returntrue;
26 }

5. 将两叉搜索树替换为排序的双链表。

与二叉树的提示词语花化同样

 1void _ToList(Node* cur, Node*& 前级)
 2    {
 3if (库尔 == 空)
 4return;
 5 6         _ToList(库尔->_left, 前级);
 7// 8         cur->_left = prev;
 9if(前级)
10             prev->_right = cur;
1112         prev = cur;
1314         _ToList(库尔->_right, 前级);
15    }
1617     Node* ToList(Node* 根)
18    {
19         Node* prev = NULL;
20        _ToList(根), 前级);
2122         Node* head = root;
23while (头) && head->左)
24        {
25             head = head->_left;
26        }
2728return head;
29     }

6.求二叉树的宽度

同样的人二叉树的宽度是指:二叉树各层杂种数字的达到高峰。

咱们了解层序遍历二叉树是应用 queue 来达到预期的目的的:每回跺脚独一杂种后,以防有左子树和右子树,摆布子树被压入 queue,这么此刻的队列中能够既使具体化赠送层的杂种,它还使具体化下苗圃杂种。。

咱们必要的是独一特定的层的杂种量子。,因而咱们必要从结的开端,记载每层的量子,到赠送层的每个杂种,在树突然出现后,按下树的左、右子树。 queue,当赠送层整个从队列中突然出现时,队列中剩的是下苗圃杂种。。尔后相对地优于利润的队列显得庞大和最大宽度。,达到高峰是队列的宽度。。终于队列是空的,利润的maxWidth执意二叉树的宽度!

 1int 宽度(杂种) 根)
 2    {
 3         queue q;
 4if (根))
 5            q.push(根));
 6int maxwidth = 1;
 7while (!())    
 8        {
 9int length = ();
10while (程度 > 0)    
11            {
12                 Node* front = ();
13                q.pop();
14if (舌前的)左)
15                {
16                     q.push(舌前的)左)
17                }
18if (舌前的)右)
19                {
20                     q.push(舌前的)右)
21                }
22            }
23             maxwidth = maxwidth > () ? maxwidth : ();
24        }
25return maxwidth;
26     }

7. 二叉树其说得中肯哪独一是均衡二叉树

二叉树中每独一杂种的摆布子树高音调的之差均以内2即为均衡二叉树。这么当一颗二叉树的各种的子树都是均衡二叉树时,它本身必定为均衡二叉树,用很手势可以循环断定。二叉树其说得中肯哪独一是均衡二叉树。信号列举如下:

 1//--断定一棵二叉树其说得中肯哪独一是均衡二叉树 2bool IsBalance(Node* 根)  //O(N^2) 3    {
 4if (根) == 空)
 5        {
 6returnfalse;
 7        }
 8int left = Depth(根)->左)
 9int right = Depth(根)->右)  
10return ABS(右) - 左) < 2 && IsBalance(根)->左) && IsBalance(根)->右)
11     }

这种方法借助摆布的高音调的相对地来决定其说得中肯哪独一为二叉树,需屡次遍历二叉树,工夫复杂性为O(n ^ 2)。上面是O(n)的独一算法:

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

 8.二叉树其说得中肯哪独一为另一颗树的子树

断定一颗二叉树其说得中肯哪独一是另一颗树的子树。

 先在找二叉树里找根杂种,找到后,决定后续杂种其说得中肯哪独一相当。,以防相当,它是一棵子树。。

 1bool JudgeNextTree(Node* next, Node* 子女) //两棵树的鼻杂种的值相当。,别的杂种其说得中肯哪独一相当 2    {
 3if (子女) == 空)
 4        {
 5returntrue;
 6        }
 7if 下一步 == 空)
 8        {
 9returnfalse;
10        }
11if 下一步->_data == child->档案)    //
12        {
13return JudgeNextTree下一步->_left, child->左) && JudgeNextTree下一步->_right, child->右)
14        }
15else {
16returnfalse;  //以防摆布子女胜任的,它是一棵子树。,不然就过失17        }
18    }
19bool JudgeTree(Node* parent, Node* 子女) //决定孩子其说得中肯哪独一是双亲的子树20    {
21if (子女) == 空) //空树是无论哪一个树的子树。22        {
23returntrue;
24        }
25if (父亲) == 空)  //空树不注意空树的子树。26        {
27returnfalse;
28        }
29if (父亲)->_data == child->档案)  //赠送杂种与找到子树的根杂种的工夫相通。30        {
31return JudgeNextTree(父亲), 子女);  //从相当杂种断定它其说得中肯哪独一是子树32        }
33elseif (JudgeTree(父亲)->_left, child->左) == true)  //决定赠送杂种的左子树其说得中肯哪独一与TH相通。34        {
35returntrue;
36        }
37else {
38return JudgeTree(父亲)->_right, child->右)  //决定赠送杂种的右子树其说得中肯哪独一与39        }
40     }

发表评论

电子邮件地址不会被公开。 必填项已用*标注