C语言刷二叉树(三)提高部分
236. 二叉树的最近公共祖先
/* * 1.后序遍历 * 2.左子树和右子树每颗树都完整的遍历1遍 * 3.回溯,利用左子树和右子树的返回值,来判断最近公共祖先 */ struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) { if (root == p || root == q || root == NULL) return root; struct TreeNode *left = lowestCommonAncestor(root->left, p, q); struct TreeNode *right = lowestCommonAncestor(root->right, p, q); if (left != NULL && right != NULL) return root; if (left == NULL && right != NULL) return right; return left; }
归纳如下三点:
-
求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从低向上的遍历方式。
-
在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
-
要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
235. 二叉搜索树的最近公共祖先
/* 解法一:利用二叉搜索树的性质 */ struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) { int leftVal = p->val < q->val ? p->val : q->val; int rightVal = p->val > q->val ? p->val : q->val; while (root != NULL) { if (root->val > leftVal && root->val < rightVal) { return root; } else if (root->val == leftVal || root->val == rightVal) { return root; } else if (root->val > rightVal) { root = root->left; } else { root = root->right; } } return NULL; } /* 解法二:暴力解法,没有利用二叉搜索树的特性 */ struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) { if (root == NULL || root == p || root == q) return root; struct TreeNode *left = lowestCommonAncestor(root->left, p, q); struct TreeNode *right = lowestCommonAncestor(root->right, p, q); if (left != NULL && right != NULL) { return root; } else if (left == NULL && right != NULL) { return right; } return left; }