题目如上图。给定我们一个二叉树和其中的两个结点,让我们找出这两个结点的最小公共祖先,如上图中的7、4最小公共祖先是2。题目并不复杂。
我的思路:
要找到两个结点的最小公共祖先,肯定要先找到这两个结点吧,那么肯定得遍历(我用的是按层遍历)。然而遍历找到这两个结点的位置了,我们却“丢失”了他们祖先的信息,所以得想一个办法在遍历时把他们的祖先的信息记录下来。这里我用到了两个数组记录每个结点双亲的信息,一个数组装结点指针,一个数组装双亲结点的位置,这样就能通过这两个数组找到每一个结点的祖先信息了,并通过第一个数组返回结果。
继续这个思路,我们一边遍历二叉树,一边记录信息,当把指定的两个结点都找到时就可以退出遍历了(找到指定结点时需记录下它们在数组中的位置)。
完成遍历后,就可以通过两个数组记录的祖先信息查找两个结点的最小公共祖先了。
举个例子:
对于完全二叉树{-1,0,3,-2,4,NULL,NULL,8},指定结点{0}和{8},我们按层遍历得到的结点依次排序为:-1,0,3,-2,4,8;它们的序号自然是:0,1,2,3,4,5;第二个数组记录的双亲位置为:-1(根结点无双亲),0,0,1,1,3。这时查找最小祖先便变得十分容易,就不多说了。贴上代码:
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { TreeNode* pointMemory[10000]; //装指针的数组 int parentIDMemory[10000]; //装双亲位置的数组 if(root == NULL)return NULL; if(p == root || q == root)return root; parentIDMemory[0] = -1; pointMemory[0] = root; int i, ID, pNumber, qNumber; i = 1; ID = 0; pNumber = qNumber = -1; //用于记录两个结点位置 while(ID <= i) //按层遍历,记录信息 { if(pointMemory[ID]->left != NULL) { if(pointMemory[ID]->left == p) //找到指定结点,下同 pNumber = i; if(pointMemory[ID]->left == q) qNumber = i; parentIDMemory[i] = ID; pointMemory[i] = pointMemory[ID]->left; if(pNumber != -1 && qNumber != -1) //找到两个指定结点,退出遍历 break; i++; } if(pointMemory[ID]->right != NULL) { if(pointMemory[ID]->right == p) pNumber = i; if(pointMemory[ID]->right == q) qNumber = i; parentIDMemory[i] = ID; pointMemory[i] = pointMemory[ID]->right; if(pNumber != -1 && qNumber != -1) break; i++; } ID++; } while(parentIDMemory[pNumber] != -1 && parentIDMemory[qNumber] != -1) //查找最小公共祖先 { if(parentIDMemory[pNumber] == qNumber) return pointMemory[qNumber]; if(parentIDMemory[qNumber] == pNumber) return pointMemory[pNumber]; if(parentIDMemory[pNumber] == parentIDMemory[qNumber]) return pointMemory[parentIDMemory[pNumber]]; if(pNumber > qNumber) pNumber = parentIDMemory[pNumber]; else qNumber = parentIDMemory[qNumber]; } return NULL; } };
提交的结果:
这个方法代码量很大,但思路却很简单朴实O__O,我这种代码渣暂时只想到这里,看到网上的一些方法只能默默膜拜。