236. Lowest Common Ancestor of a Binary Tree(python+cpp)

题目:

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]

        _______3______
       /              \
    ___5__          ___1__    
   /      \        /      \    
   6      _2       0       8
         /  \
         7   4 

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 
Output: 3
Explanation: The LCA of of nodes 5 and 1 is 3. 

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of 
itself according to the LCA definition. 

Note:

All of the nodes’ values will be unique.
p and q are different and both values will exist in the binary tree.

解释:
1.是一个普通的二叉树,不是BST,所以不能根据根节点大于其中一个结点并且小于另一个结点来判断
2.没有指向父节点的指针,所以不能直接用“寻找两个链表的第一个公共结点”来解决
3.不断遍历并判断,如果某个结点的两个子树分别包含这两个结点,但是它的某个子结点中不同时包含这两个结点,那么这个结点就是公共结点,这个方法会重复计算(大神的解法)
4.先用两个链表存储从根节点到两个子节点的路径(回溯法),再判断路径的公共结点(这样的两个链表是从公共结点开始分叉,而不是先分叉再融合,所以判断的时候不需要双指针来回走,更加简单)
问题:二叉树结点的值有没有可能是一样的?
第一种解法,python代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if root in (None,p,q):
            return root
        left=self.lowestCommonAncestor(root.left,p,q)
        right=self.lowestCommonAncestor(root.right,p,q)
        return root if left and right else left or right

c++代码,注意 leftrightNULL初始化:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> tmp={NULL,p,q};
        if (count(tmp.begin(),tmp.end(),root))
            return root;
        TreeNode* left=NULL;
        TreeNode* right=NULL;
        if (root->left)
            left=lowestCommonAncestor(root->left,p,q);
        if(root->right)
            right=lowestCommonAncestor(root->right,p,q);
        if (left&&right)
            return root;
        else if (left)
            return left;
        else
            return right;
            
    }
};

第二种解法,由于回溯的最终结果并不是返回路径,或者把路径保存在某个结果中,所以不能用path+[new_val]的方式回溯,而应该用push()+pop()的方式,再说,在别的语言里面也没有这种直接相加的办法,只有python有,用别的语言实现回溯都是push()+pop()
python代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        #不需要重新定义链表的数据结构,用一个list存储TreeNode即可
        def getPath(root,node,path):
            if root==None:
                return None
            path.append(root)
            if root==node:
                return True
            found=False
            if not found and root.left:
                found= getPath(root.left,node,path)
            if not found and root.right:
                found=getPath(root.right,node,path)
            if not found:
                path.pop()
            return found
        def getLastCommonNode(path1,path2):
            pLast=None
            i=0
            while i<min(len(path1),len(path2)):
                if path1[i]==path2[i]:
                    pLast=path1[i]
                    i+=1
                else:
                    break
            return pLast
        if not root or not p or not q:
            return None
        #由于不是只有一个path,所以不能用self.path,要把path作为一个参数传入函数
        path1=[]
        path2=[]
        getPath(root,p,path1)
        getPath(root,q,path2)
        return getLastCommonNode(path1,path2)

c++代码,学习一下用cpp实现回溯:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*>path1,path2;
        bool bool1=getPath(root,path1,p);
        bool bool2=getPath(root,path2,q);
        TreeNode*lp=NULL;
        int i=0;
        while(i<min(path1.size(),path2.size()))
        {
            if (path1[i]==path2[i])
            {   
                lp=path1[i];
                i+=1;
            }
            else
                break;
        }
        return lp;
    }
    bool getPath(TreeNode*root,vector<TreeNode*>& path,TreeNode* target)
    {
        if(!root)
            return NULL;
        path.push_back(root);
        bool found=false;
        if (root==target)
            return true;   
        if (!found &&root->left)
            found=getPath(root->left,path,target);
        if(!found &&root->right)
            found=getPath(root->right,path,target);
        if (!found)
            path.pop_back();
        return found;
    }
};

总结:
python中,return a or b的意思是,当a不为空则返回a,否则返回b。

你可能感兴趣的:(LeetCode)