Binary Tree 9 - Others
1. Lowest Common Ancestor
Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
方法1,找到2点的path,再遍历2条path找公共节点
// 返回,是否找到了path,便于提前返回
bool getNodePath(TreeNode * root, TreeNode * node, vector<TreeNode *> &path) {
if(root == nullptr) return false; // !别忘了边界
path.push_back(root);
if(root == node) return true; // 找到了,也要加进去,否则父子关系的会出错
// 如果找到了,不需要再继续dfs,直接返回,剪枝
if(getNodePath(root->left, node, path) || getNodePath(root->right, node, path)) {
return true;
}
path.pop_back();
return false;
}
TreeNode * lowestCommonAncestor(TreeNode * root, TreeNode * A, TreeNode * B) {
if(root == nullptr) return nullptr;
vector<TreeNode *> pathA, pathB;
if(!getNodePath(root, A, pathA)) return nullptr;
if(!getNodePath(root, B, pathB)) return nullptr;
// 找2条路径上第一次分开的点就可以了
TreeNode *lca = root;
for(int i = 0; i < pathA.size() && i < pathB.size(); i++) {
if(pathA[i] != pathB[i]) { // 说明已经分开了
return lca;
}
lca = pathA[i];
}
return lca; // 已经出来了,AB为父子关系的这种情况
}
拓展到普通树
a) 二叉树拓展到了普通数中,根节点到它的路径 这个O(n) Space的方案
bool GetNodePath(TreeNode* pRoot, TreeNode* pNode, list<TreeNode*>& path){
if(pRoot == pNode)
return true;
path.push_back(pRoot);
bool found = false;
vector<TreeNode*>::iterator i = pRoot->m_vChildren.begin();
while(!found && i < pRoot->m_vChildren.end()) { //一找到就跳出
found = GetNodePath(*i, pNode, path);
++i; //扫描所有的子节点
}
if(!found)
path.pop_back(); //注意!弹出
return found; //返回是否能找到, 即有没有该节点
}
b) 求2个链表的,公共节点
TreeNode* GetLastCommonNode(const list<TreeNode*>& path1, const list<TreeNode*>& path2){
list<TreeNode*>::const_iterator iterator1 = path1.begin();
list<TreeNode*>::const_iterator iterator2 = path2.begin();
TreeNode* pLast = NULL;
while(iterator1 != path1.end() && iterator2 != path2.end()){
if(*iterator1 == *iterator2)
pLast = *iterator1; //*iter是<>里的内容,即treenode*
else
break;
iterator1++;
iterator2++;
}
return pLast;
}
c) 上述2个函数,也可以用到求树中2个节点的距离:先求最低公共祖先,然后根据2个list求距离
方法2,O(1) Space的方案
// 在root为根的二叉树中找A,B的LCA:
// 如果找到了就返回这个LCA
// 如果只碰到A,就返回A
// 如果只碰到B,就返回B
// 如果都没有,就返回null
TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *A, TreeNode *B) {
if(root == NULL || root == A || root == B) {
return root; // 如果是A是B的父节点这种情况,直接返回A即可
}
TreeNode *left = lowestCommonAncestor(root->left, A, B);
TreeNode *right = lowestCommonAncestor(root->right, A, B);
if(left != NULL && right != NULL) {
return root; // 左右各有1个点,找到了,返回这个LCA; 并且可以一直返回到根root
}
if(left == NULL && right == NULL) {
return NULL; // 左右都没有
}
return left ? left : right; // 只碰到了A,B中的某一个,返回它
}
If node A or node B may not exist in tree: Lowest Common Ancestor III Harder!
struct Result {
bool isAexist;
bool isBexist;
TreeNode* answer;
Result(bool isA, bool isB, TreeNode* node)
: isAexist(isA), isBexist(isB), answer(node) {}
};
Result core(TreeNode* root, TreeNode* A, TreeNode* B) {
if (root == NULL) return Result(false, false, NULL); // 这一句有区别
Result left = core(root->left, A, B); //后序遍历,之前不返回
Result right = core(root->right, A, B); // 一直走到叶节点
// set Result
TreeNode* curAnswer;
bool isA = left.isAexist || right.isAexist || (root == A);
bool isB = left.isBexist || right.isBexist || (root == B);
if ((left.answer != NULL && right.answer != NULL) ||
(root == A || root == B)) {
curAnswer = root;
} else if (left.answer == NULL && right.answer == NULL) {
curAnswer = NULL;
} else {
curAnswer = left.answer == NULL ? right.answer : left.answer;
}
return Result(isA, isB, curAnswer);
}
TreeNode* lowestCommonAncestor3(TreeNode* root, TreeNode* A, TreeNode* B) {
// if (root == NULL) return NULL;
Result res = core(root, A, B);
if (res.isAexist && res.isBexist) return res.answer;
return NULL; // 都不存在
}
2. Lowest Common Ancestor II
The node has an extra attribute parent which point to the father of itself. The root's parent is null.
ParentTreeNode *lowestCommonAncestorII(ParentTreeNode *root,
ParentTreeNode *A,
ParentTreeNode *B) {
if(root == NULL || root == A || root == B)
return root;
stack<ParentTreeNode*> pathA;
ParentTreeNode *node = A;
while(node != NULL) {
pathA.push(node);
node = node->parent;
}
stack<ParentTreeNode*> pathB;
node = B;
while(node != NULL) {
pathB.push(node);
node = node->parent;
}
ParentTreeNode *last;
while(!pathA.empty() && !pathB.empty()) {
if(pathA.top() != pathB.top()) {
return last;
}
last = pathA.top();
pathA.pop();
pathB.pop();
}
return last; // 题目规定肯定有答案,跳出了,说明A是B的父亲
}
3. Complete Binary Tree
Check a binary tree is completed or not. A complete binary tree is a binary tree that every level is completed filled except the deepest level. In the deepest level, all nodes must be as left as possible.
ResultType方法
struct Result {
int height;
bool iscomplete;
bool isfull;
Result(int i = -1, bool is = false, bool full = false)
: height(i), iscomplete(is), isfull(full) {}
};
Result isCompleteHelper(TreeNode* root) {
if (root == NULL) {
return Result(0, true, true);
}
Result left = isCompleteHelper(root->left);
Result right = isCompleteHelper(root->right);
if (left.iscomplete == false || right.iscomplete == false) {
return Result(); // false
}
/* // do not need
if(left.height < right.height || left.height - right.height > 1) {
return Result();
}*/
// 相等,left is Full, right is complete
if (left.height == right.height) {
if (left.isfull && right.iscomplete) {
return Result(left.height + 1, true, right.isfull);
}
return Result();
}
// left is complete, right is full
if (left.height == right.height + 1) {
if (left.iscomplete && right.isfull) {
return Result(left.height + 1, true, false);
}
return Result();
}
return Result();
}
bool isComplete(TreeNode* root) {
if (root == NULL) return true;
return isCompleteHelper(root).iscomplete;
}
推荐方法,层序遍历,叶节点填洞,最后的结尾都是洞
bool isComplete(TreeNode* root) {
if (root == NULL) return true;
vector<TreeNode*> q; // use vector, in order to index it
q.push_back(root);
for (int i = 0; i < q.size(); i++) {
TreeNode* node = q[i];
if (node == NULL) {
continue;
}
q.push_back(node->left);
q.push_back(node->right);
}
int lastNotNULL = -1;
for (int i = q.size() - 1; i >= 0; i--) {
if (q[i] != NULL) {
lastNotNULL = i;
break;
}
}
for (int i = lastNotNULL - 1; i > 0; i--) {
if (q[i] == NULL) {
return false;
}
}
return true;
}
4. Binary Tree Longest Consecutive Sequence
Given a binary tree, find the length of the longest consecutive sequence path.
The longest consecutive path need to be from parent to child (cannot be the reverse).
DFS - Traverse:
// 好理解,边Traverse,边记录
void dfs(TreeNode* root, int& result, int curLen, int lastNum) {
if (root == NULL) {
return;
}
if (root->val == lastNum + 1)
curLen++;
else
curLen = 1; // 不连续,归位
if (curLen > result) result = curLen;
dfs(root->left, result, curLen, root->val);
dfs(root->right, result, curLen, root->val);
}
int longestConsecutive(TreeNode* root) {
int result = -1;
dfs(root, result, 0, 0);
return result;
}
DFS - Divide & Conquer:
// 不太好理解:dfs函数代表,加上左/右子树后,返回最长值
int dfs(TreeNode* root, int curLen, int lastNum) {
if (root == NULL) {
return 0;
}
if (root->val == lastNum + 1)
curLen++;
else
curLen = 1; // 不连续,归位
// 区别:
int leftLongest = dfs(root->left, curLen, root->val);
int rightLongest = dfs(root->right, curLen, root->val);
return max(curLen, max(leftLongest, rightLongest));
}
int longestConsecutive(TreeNode* root) { return dfs(root, 0, 0); }
5. Binary Tree Paths
void dfs(TreeNode* root, vector<string>& res, vector<int>& line) {
if (root->left == NULL && root->right == NULL) {
string tmp;
for (int i = 0; i < line.size(); i++) {
tmp += to_string(line[i]) + "->";
}
tmp += to_string(root->val); // 最後一個直接加上,不放line了
res.push_back(tmp);
return;
}
line.push_back(root->val);
if (root->left != NULL) dfs(root->left, res, line);
if (root->right != NULL) dfs(root->right, res, line);
line.pop_back();
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if (root == NULL) return res;
vector<int> line;
dfs(root, res, line);
return res;
}
// 或直接用string,简洁!
void dfs(TreeNode* root, vector<string>& res, string line) { // string无&,拷贝
if (root->left == NULL && root->right == NULL) {
res.push_back(line);
return;
}
if (root->left != NULL)
dfs(root->left, res, line + "->" + to_string(root->left->val));
if (root->right != NULL)
dfs(root->right, res, line + "->" + to_string(root->right->val));
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if (root == NULL) return res;
dfs(root, res, to_string(root->val));
return res;
}