求二叉树的最小公共祖先。虽然LCA的定义很好理解,但要用程序逻辑表达出来不简单。自己想的思路是将两个目标节点的遍历路径记录下来然后找出第一个相同的节点。无奈用C的话没有vector不方便就作罢。
网上参考了下,发现以下AC代码的逻辑还是很巧妙的,而且代码量很小:
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {
if (!root)
return NULL;
if (root == p || root == q)
return root;
struct TreeNode *lnode = lowestCommonAncestor(root->left, p, q);
struct TreeNode *rnode = lowestCommonAncestor(root->right, p, q);
if (lnode && rnode)
return root;
if (lnode)
return lnode;
else
return rnode;
}
刚开始一下还没看懂,然后脑子里输入数据过几遍流程大致就知道了。
基本思路是p,q肯定分别在最小公共祖先的左右子树中。程序中巧妙的地方在于返回的值一是代表了目标节点,二是在本层的回退过程中该返回值(从上一个递归回退回来的)还可以通过是否为NULL来表示该层子树下是否有目标节点。递归深搜后回退的流程就相当于记录从目标节点往上一层回退的路径,只要在此过程中判断是否其子树下有目标节点就可以得到答案(个人感觉此段文字描述没有很准确的描述流程)。
这种思路的程序在不知道解法的情况下我是硬想不出来的,但是如果写过类似逻辑的程序借鉴下却又有可能写出来。所以有时候我觉得写程序很像读书时的作文课,每次作文课我都是想用自己认为的有创造性的语言和思路来写但往往分都不高也就是硬想的方式,但如果借鉴看过的读者青年文摘之类的文章形式来写的话虽然可以高分但又觉得不是自己原创的形式没意思。所以我还是很佩服那种从无到有生造算法的人,不是那种站在巨人肩膀上的人,而是本身就是巨人的人。