1 /*
 2  * @Author: your name
 3  * @Date: 2020-11-12 09:13:41
 4  * @LastEditTime: 2020-11-12 09:31:05
 5  * @LastEditors: your name
 6  * @Description: In User Settings Edit
 7  * @FilePath: \git\leetcode\236.二叉树的最近公共祖先.cpp
 8  */
 9 /*
10  * @lc app=leetcode.cn id=236 lang=cpp
11  *
12  * [236] 二叉树的最近公共祖先
13  */
14 
15 // @lc code=start
16 /**
17  * Definition for a binary tree node.
18  * struct TreeNode {
19  *     int val;
20  *     TreeNode *left;
21  *     TreeNode *right;
22  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
23  * };
24  */
25 class Solution {
26 public:
27 /*如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
28 
29 使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现如何这个条件的节点,就是最近公共节点了。
30 
31 递归三部曲:
32 
33 确定递归函数返回值以及参数
34 确定终止条件
35     如果找到了 节点p或者q,或者遇到空节点,就返回。
36 确定单层递归逻辑
37 
38 在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,
39 如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
40 
41 */
42     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
43         if(root==nullptr||root==p||root==q)
44             return root;
45         TreeNode *left = lowestCommonAncestor(root->left, p, q);
46         TreeNode *right = lowestCommonAncestor(root->right, p, q);
47         if(left&&right)
48             return root;
49         if(!left&&right)
50             return right;
51         return left;
52     }
53 };
54 /*
55 总结:求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从低向上的遍历方式。
56 
57 在回溯的过程中,必然要遍历整颗二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
58 要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
59 */
60 // @lc code=end