面试总结之-树 (二)

2014-11-24 01:44:18 · 作者: · 浏览: 4
if(!root) { num = 0;return NULL;}
int leftnum =0,rightnum=0;
node* left = lca(root->left,p1,p2,leftnum); //左子树找到直接返回
if(leftnum==2) return left;
node* right = lca(root->right,p1,p2,rightnum);//右子树
if(rightnum==2) return right;
num = left+right;
if(p1==root) num++;
if(p2==root) num++;
if(num==2) return root; //找不到计算当前树
return NULL; //都找不到返回NULL
}
这部分都是一个题目一个解,没总结出啥共性。

四.序列化与发序列化。

一个序列化的方法可以参考这个:http://blog.csdn.net/ssjhust123/article/details/7777665这种方法用一个不出现的字符作为终结符。如果题目说节点的value是一个可以允许任意字符的string的话,就用转义字符解决吧。既然树的序列化,那就避免不了树节点的序列化了,如果树节点的value是一个字符串数组,那么,树序列化的子问题就是这个字符串序列化的问题,没别的~继续用转义字符解决吧。

最后一点要注意的,递归处理树的时候,递归返回条件经常用到两种:


[cpp] (1) if(!node) return;
(2) if(!node->left&&!node->right) return;

(1) if(!node) return;
(2) if(!node->left&&!node->right) return;
这两种差别在于,第一种会在非叶子节点return回去(比如当前面的节点有右儿子没有左儿子时,在进入左儿子后会有一个return,当然,要是递归前你有加一个if(root->left) Recursive()的话,是不会进入这个NULL节点的,不过我为了简洁,一般不加);第二种只有到了叶子节点才会返回。这两个还是有区别的,差别就在于题目的解是不是必须在叶子节点出现,比如让你找root到叶子节点的最短距离,一般就用第二个判断条件比较合适,具体自己写写体会一下吧。

另外,如果对于要不要往某个儿子递归进行了判断(if(root->left)),那么你就不知道有没有进入这个儿子节点,就不知道你的这个儿子节点需要更新的变量有没有被更新,这时候这些变量的初始化就要额外小心。

这段话的意思还是给个例子来解释下吧,比如如下代码:


[cpp] int Max(TreeNode* root){
int left,right;
if(!root->left && !root->right)
return root->val;
if(root->left) left = Max(root->left);
if(root->right) right = Max(root->right);
return max(root->val,max(left,right));
}

int Max(TreeNode* root){
int left,right;
if(!root->left && !root->right)
return root->val;
if(root->left) left = Max(root->left);
if(root->right) right = Max(root->right);
return max(root->val,max(left,right));
}这种代码时有问题的,因为left和right的值有可能没有初始化,你不确定程序有没有递归处理左、右部分。它用了(2)这种递归返回条件,要是想用这个条件的话,就需要对left,right进行初始化,比如:

[cpp] left = right = MIN_INT;

left = right = MIN_INT;如果用(1)这个返回条件的话,可以写成:


[cpp] int Max(TreeNode* root){
if(!root) return MIN_INT;
return max(root->val,max(Max(root->left),Max(root->right)));
}

int Max(TreeNode* root){
if(!root) return MIN_INT;
return max(root->val,max(Max(root->left),Max(root->right)));
}
相对来说,用(1)就要简洁一点。这里不一定要用(2)的原因就是上面说的:解不是必须在叶子节点出现。因为if(!root->left && !root->right)这种条件就是为了判断root是不是一个叶子,而例子中的Max函数根本不需要一定要求这个值所在的位置是一个叶子。


简单说,能用(1)的尽量用(1)(比如上面的LCA,也可以改成用(2)的),但是对于前面一定要在叶子节点结束的就没办法了,这时候,进行递归的时候将需要判断if(root->child),如果这个函数有变量返回,比如一个depth,那就要注意这个变量的值,因为这个递归你不一定会进入的,depth如果没有初始化过的话,又没有进入递归,那么depth可能是个不可预测的值,后面需要用到depth的话注意判断,也可以先给depth一个值,比如depth返回的是最大深度,可以把depth初始化为INT_MIN 。

对于递归处理树时,首先想好使用(1)还是(2)作为终止条件(主要判断是不是只能在叶子终止),如果用了(2)记得在递归时判断儿子是不是为NULL,然后变量需要初始化。