Leetcode刷题——树篇2

2、树(简单篇2)

2.1、965. 单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false。

示例 1:
在这里插入图片描述

输入:[1,1,1,1,1,null,1] 输出:true 示例 2:
在这里插入图片描述

输入:[2,2,2,5,2] 输出:false

提示:

给定树的节点数范围是 [1, 100]。 每个节点的值都是整数,范围为 [0, 99] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/univalued-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:题意不难理解,判断一棵二叉树的结点值是否唯一,是就返回true,否则返回false。
提示还给出了节点数的范围,至少有一个结点。
如果是一个数组,判断值是否唯一,很简单,遍历一遍数组就行了,如果发现有与第一个元素值不同的就返回false,否则返回true。
现在问题是数组变成二叉树,二叉树也是有遍历的啊,前中后,任君选择。

简单的框架:

bool tag = true;
void isUniqueTree(TreeNode* root,int val,bool &tag){
	if(root==NULL||tag==false) return;//树为空或tag为false,就没必要遍历了
	if(root->val!=val) {tag=false;return;}//发现一个不等的值,置tag为false
	isUniqueTree(root->left,val,tag);
	isUniqueTree(root->right,val,tag);
}

题解代码(C++):

/**
 * 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:
    bool isUnivalTree(TreeNode* root) {
        bool tag = true;
        isUnivalTreeHelper(root,root->val,tag);
        return tag;
    }
    void isUnivalTreeHelper(TreeNode* root,int val,bool &tag){
        if(root==NULL||tag==false) return ;
        if(root->val!=val) {tag = false;return;}
        isUnivalTreeHelper(root->left,val,tag);
        isUnivalTreeHelper(root->right,val,tag);
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private boolean isUnivalTreeHelper(TreeNode root,int val){
    //Java 与 C++ 有区别
        if(root==null) return true;
        if(root.val!=val) return false;
        else return isUnivalTreeHelper(root.left,val) && isUnivalTreeHelper(root.right,val);
    }
    public boolean isUnivalTree(TreeNode root) {
        return isUnivalTreeHelper(root,root.val);
    }
}

题解代码(Python):

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

class Solution:
    def isUnivalTree(self, root: TreeNode) -> bool:
        return self.preOrderHelper(root,root.val)

    def preOrderHelper(self,root:TreeNode,val:int)->bool:
        if root is None:
            return True
        else:
            if root.val== val:
                return self.preOrderHelper(root.left,val) and self.preOrderHelper(root.right,val)
            else:
                return False

2.1、669. 修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L)
。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

示例 1:

输入:
在这里插入图片描述
L = 1 R = 2

输出:
在这里插入图片描述
示例 2:

输入:
在这里插入图片描述
L = 1 R = 3

输出:
在这里插入图片描述
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trim-a-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:修剪二叉搜索树,又是二叉搜索树,莫名其妙想到中序遍历…
修剪就相当于增删查改的删吧,换个问题:如果是一个数组,只保留给定范围[L,R]的元素,很简单就想到遍历了是吧,换成二叉搜索树的话同样也是这样,没什么难度的。

简单框架:

void traversal(TreeNode* root){
	if(root==NULL) return;
	traversal(root->left);
	//判断是否删除删除
	traversal(root->right);
}

事实真的这么简单吗?其实并不是的,树的删除(就地修改)一定要谨慎,因为它并不像是数组那样的连续结构,树的删除如果出错,就是一整个结构的破坏,最常见就是丢失指针的问题,很容易失去一些数据,从而引起整个程序崩溃。
就如上面的代码,一旦root被删除了,那么traversal(root->right) 就会抛出异常,root都为空了,哪还有右孩子,所以树的删除(就地修改)一定要谨慎!

上面举了个错误的想法,下面再来谈谈如何分析:
在这里插入图片描述
先看一棵常见的二叉搜索树,这么一看觉得是有点复杂,毕竟有12个结点。我们来简化一下:
在这里插入图片描述
简化成一个根节点,还有A、B两棵子树,那么问题来了:修剪以root为根结点的树,是不是相当于先修剪A子树,再修剪B子树,再看看根结点是否需要修剪,把一件事情细分成三个小任务,逐一击破。
那么修剪A子树和修剪B子树,是不是相当于调用本身的函数,就是用递归了嘛!两个小任务完成。
根结点是否需要修剪,如果不需要修剪,那么只需要修剪A、B子树就完成了。如果需要修剪,那么该保留A子树的修剪结果呢?还是保留B子树的修剪结果呢?
等等,有没有发现先做根结点的判断效率更高?既然根结点是要被修剪的,那么只需要保留一边的子树就行,那就没必要先修剪了子树再判断要保留的子树。

简单的框架:

TreeNode* trimBST(TreeNode* root,int L,int R){
	if(root==NULL) return NULL;
	if(root->val<L) return trimBST(root->right,L,R);//根节点需要被修剪,并在值还在[L,R]的左边,自然要返回右子树的修剪结果了
	else if(root->val>R) return trimBST(root->left,L,R);//根节点需要被修剪,并在值还在[L,R]的右边,自然要返回左子树的修剪结果了
	else {//既然根节点的值在[L,R]内,那么就去修剪左右子树吧
		root->left = trimBST(root->left,L,R);
		root->right = trimBST(root->right,L,R);
		return root;
	}
}

题解代码(C++):

/**
 * 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* trimBST(TreeNode* root, int L, int R) {
        if(root==NULL) return NULL;
        if(root->val<L) return trimBST(root->right,L,R);
        else if(root->val>R) return trimBST(root->left,L,R);
        else{
            root->left = trimBST(root->left,L,R);
            root->right = trimBST(root->right,L,R);
            return root;
        }
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode trimBST(TreeNode root, int L, int R) {
        if(root==null) return null;
        if(root.val<L) return trimBST(root.right,L,R);
        else if (root.val>R) return trimBST(root.left,L,R);
        else{
            root.left = trimBST(root.left,L,R);
            root.right = trimBST(root.right,L,R);
            return root;
        }
    }
}

题解代码(Python):

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

class Solution:
    def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
        if root is None:
            return None
        if root.val <L:
            return self.trimBST(root.right,L,R)
        elif root.val>R:
            return self.trimBST(root.left,L,R)
        else:
            root.left=self.trimBST(root.left,L,R)
            root.right=self.trimBST(root.right,L,R)
            return root

2.3、102. 二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例: 二叉树:[3,9,20,null,null,15,7],

    3    
   / \   
  9  20
 /  \    
15   7 

返回其层次遍历结果: [   [3],   [9,20],   [15,7] ]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:现在碰到另一种遍历方式:层次遍历,之前的前中后遍历方式都是属于深度优先,而层次遍历是属于广度优先。
层次遍历就是把树的一层层分开遍历,每一层从左到右进行遍历,从例子不难看出。
层次遍历的实现最简单就是教科书上的使用辅助的队列,队列有个特性就是先进先出(FIFO)。
在这里插入图片描述
首先把根节点加入到队列中去,这是第一层遍历的开始,
遍历的过程就是:从队列中取出一个元素,并把它的左右孩子(如果有)加入到队列中。
在这里插入图片描述
现在这样是第二层遍历的开始,还是取队列的元素,还是和刚刚的步骤一样,这样一直到队列没有元素为止,层次遍历也就结束了。
在这里插入图片描述
在这里插入图片描述

简单框架:

void traversal(TreeNode* root){
	queue;
	queue.push(root);
	while(!queue.empty()){
 	    element = queue.pop()
		visit(element)
		queue.push(element->left)//如果有左孩子
		queue.push(element->left)//如果有右孩子
}

题目要求返回的是二维数组,同一层的结点值在同一数组,所以实现上需要一点小修改。

题解代码(C++):

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if(root!=NULL) q.push(root);
        while(!q.empty()){
            int count = q.size();
            vector<int> v;
            while(count){
                TreeNode* element = q.front();
                q.pop();
                v.push_back(element->val);
                if(element->left!=NULL) q.push(element->left);
                if(element->right!=NULL) q.push(element->right);
                count--;
            }
            res.push_back(v);
        }
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        if (root!=null) q.offer(root);
        while(!q.isEmpty()){
            List<Integer> v = new ArrayList<Integer>();
            int count = q.size();
            while(count>0){
                TreeNode element = q.poll();
                v.add(element.val);
                if(element.left!=null) q.offer(element.left);
                if(element.right!=null)  q.offer(element.right);
                count--;
            }
            res.add(v);
        }
        return res;
    }
}

题解代码(Python):

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        res = []
        queue = []
        if root is not None:
            queue.append(root)
        while(len(queue)>0):
            count = len(queue)
            v = []
            while count>0:
                element = queue.pop(0)
                v.append(element.val)
                if element.left is not None:
                    queue.append(element.left)
                if element.right is not None:
                    queue.append(element.right)
                count-=1
            res.append(v)
        return res

2.4、107. 二叉树的层次遍历 II

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如: 给定二叉树 [3,9,20,null,null,15,7],

    3   
   / \   
  9  20
 /  \    
15   7 

返回其自底向上的层次遍历为:

[ [15,7], [9,20], [3] ]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:和上面的一样,只不过输出结果倒着输出而已。
直接贴代码。

题解代码(C++):

/**
 * 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:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
         vector<vector<int>> res;
        queue<TreeNode*> q;
        if(root!=NULL) q.push(root);
        while(!q.empty()){
            int count = q.size();
            vector<int> v;
            while(count){
                TreeNode* element = q.front();
                q.pop();
                v.push_back(element->val);
                if(element->left!=NULL) q.push(element->left);
                if(element->right!=NULL) q.push(element->right);
                count--;
            }
            res.push_back(v);
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        if (root!=null) q.offer(root);
        while(!q.isEmpty()){
            List<Integer> v = new ArrayList<Integer>();
            int count = q.size();
            while(count>0){
                TreeNode element = q.poll();
                v.add(element.val);
                if(element.left!=null) q.offer(element.left);
                if(element.right!=null)  q.offer(element.right);
                count--;
            }
            res.add(v);
        }
        Collections.reverse(res);
        return res;
    }
}

题解代码(Python):

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

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        res = []
        queue = []
        if root is not None:
            queue.append(root)
        while(len(queue)>0):
            count = len(queue)
            v = []
            while count>0:
                element = queue.pop(0)
                v.append(element.val)
                if element.left is not None:
                    queue.append(element.left)
                if element.right is not None:
                    queue.append(element.right)
                count-=1
            res.append(v)
        res.reverse()
        return res

2.5、637. 二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.

示例 1:

输入:
在这里插入图片描述
输出: [3, 14.5, 11]
解释: 第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11].
注意:

节点值的范围在32位有符号整数范围内。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/average-of-levels-in-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:一连三题都是同一个框架:层次遍历,有了层次遍历的结果,求平均值还不是手到擒来。直接贴代码。不过要看题目有个注意!!!

题解代码(C++):

/**
 * 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:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if(root!=NULL) q.push(root);
        while(!q.empty()){
            int count = q.size();
            vector<int> v;
            while(count){
                TreeNode* element = q.front();
                q.pop();
                v.push_back(element->val);
                if(element->left!=NULL) q.push(element->left);
                if(element->right!=NULL) q.push(element->right);
                count--;
            }
            res.push_back(v);
        }
        vector<double> mean;
        for(int i=0;i<res.size();i++){
            long temp = 0L;//要注意溢出问题
            for(int j=0;j<res[i].size();j++){
               temp += res[i][j];
            }
            mean.push_back((double)temp/res[i].size());
        }
        return mean;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        if (root!=null) q.offer(root);
        while(!q.isEmpty()){
            List<Integer> v = new ArrayList<Integer>();
            int count = q.size();
            while(count>0){
                TreeNode element = q.poll();
                v.add(element.val);
                if(element.left!=null) q.offer(element.left);
                if(element.right!=null)  q.offer(element.right);
                count--;
            }
            res.add(v);
        }
        List<Double> mean = new ArrayList<Double>();
        for(int i=0;i<res.size();i++){
            long temp =0;
            for(int j=0;j<res.get(i).size();j++){
                temp+=res.get(i).get(j);
            }
            mean.add((double)temp/res.get(i).size());
        }
        return mean;
    }
}

题解代码(Python):

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

class Solution:
    def averageOfLevels(self, root: TreeNode) -> List[float]:
        res = []
        queue = []
        if root is not None:
            queue.append(root)
        while(len(queue)>0):
            count = len(queue)
            v = []
            while count>0:
                element = queue.pop(0)
                v.append(element.val)
                if element.left is not None:
                    queue.append(element.left)
                if element.right is not None:
                    queue.append(element.right)
                count-=1
            res.append(v)
        m = [mean(v) for v in res] #一个列表推导式搞定收工,人生苦短,我用Python
        return m 

2.6、257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
在这里插入图片描述
输出: [“1->2->5”, “1->3”]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-paths
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:仔细想想,从例子出发,从根结点到叶子结点的路径有两条,如果把这两条路径都走完,是不是相当于遍历了一遍二叉树?
那好,我们可以用遍历树的框架来试试能不能完成。
如果使用先中后遍历方式,那就是深度优先,第一次找到叶子结点的时候,其实已经走了一条路径了,例如先序遍历找到叶子节点5的时候,就已经形成了一条”1->2->5"的路径了。在访问每个结点的时候,需要记录父节点的路径,然后当前结点的值加入到路径中。
所以本题就是树的遍历的应用题。

简单框架:

void traversal(TreeNode* root,string pre_path){
	//pre_path是父节点的路径
	if(root==NULL) return ;
	string cur_path = pre_path + root->val;
	if(root->left==NULL && root->right==NULL){//已经是叶子结点
		result.append(cur_path);//加入到结果集合中
	}
	traversal(root->left,cur_path);//遍历子树的时候,把当前路径传参
	traversal(root->right,cur_path);
}

题解代码(C++):

/**
 * 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:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> res;
        if(root == NULL) return res;
        string pre="";
        binaryTreePathsHelper(root,res,pre);
        return res;
    }

    void binaryTreePathsHelper(TreeNode* root,vector<string> &res,string pre){
        if(root==NULL) return;
        pre = pre + to_string(root->val)+"->";
        if(root->left==NULL && root->right==NULL){
            res.push_back(pre.substr(0,pre.size()-2));
        }
        binaryTreePathsHelper(root->left,res,pre);
        binaryTreePathsHelper(root->right,res,pre);
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private void binaryTreePathsHelper(TreeNode root,String pre,List<String> res){
        if(root==null) return;
        String cur = pre+String.valueOf(root.val)+"->";
        if(root.left==null&&root.right==null){
            res.add(cur.substring(0,cur.length()-2));
        }
        binaryTreePathsHelper(root.left,cur,res);
        binaryTreePathsHelper(root.right,cur,res);
    }
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<String>();
        binaryTreePathsHelper(root,"",res);
        return res;
    }
    
}

题解代码(Python):

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

class Solution:
    def binaryTreePathsHelper(self,root:TreeNode,pre:str,res:List[str]):
        if root is None:
            return None;
        cur = pre+str(root.val)+"->"
        if root.left == None and root.right==None:
            res.append(cur[:-2])
        self.binaryTreePathsHelper(root.left,cur,res)
        self.binaryTreePathsHelper(root.right,cur,res)

    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        res = []
        self.binaryTreePathsHelper(root,"",res)
        return res

2.7、235. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x
的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
在这里插入图片描述 示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2和节点 8 的最近公共祖先是 6。
示例 2: 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p =2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明: 所有节点的值都是唯一的。 p、q 为不同节点且均存在于给定的二叉搜索树中。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:
在说明中有提到,结点值唯一,并且p、q不同结点,肯定存在与二叉搜索树中,所以不用管查找失败的问题。

在这里插入图片描述
情况1:要找的两个结点分别在根节点的两侧,那么很显然,最近公共祖先就是根节点。
在这里插入图片描述
情况2:如果要找的两个结点都在根节点的同一侧,那么肯定是要从子树重新开始,如上图则需要在以2为根节点的树中继续查找。
在这里插入图片描述
很显然,开始递归了。

情况3:如果根节点就是要找的元素呢,显然根节点就是最近公共祖先。

简单理理:
1、如果根节点是要查找的结点,那么最近公共祖先就是根节点。
2、如果要找的结点在根节点两侧,则根节点就是最近公共祖先。
3、如果要找的结点在根节点同一侧,则递归查找子树。

这么理理,算法就出来了。直接上代码吧。

题解代码(C++):

/**
 * 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) {
        if(root==NULL||p==NULL||q==NULL) return NULL;//判空
        if(root->val==p->val || root->val==q->val) return root;//如果根节点的值等于给出的两个值,则根节点就是最近公共祖先
        //看是同在左侧或右侧
        if(root->val>p->val && root->val>q->val) return lowestCommonAncestor(root->left,p,q);
        if(root->val<p->val && root->val<q->val) return lowestCommonAncestor(root->right,p,q);
        else return root;//不同侧就返回根节点
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null||p==null||q==null) return null;
        if(root.val==p.val || root.val==q.val) return root;
        if(root.val>p.val && root.val>q.val) return lowestCommonAncestor(root.left,p,q);
        if(root.val<p.val && root.val<q.val) return lowestCommonAncestor(root.right,p,q);
        else return root;
    }
}

题解代码(Python):

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

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root is None or p is None or q is None:
            return None
        if root.val==p.val or root.val == q.val:
            return root
        if root.val>p.val and root.val> q.val:
            return self.lowestCommonAncestor(root.left,p,q)
        if root.val<p.val and root.val <q.val:
            return self.lowestCommonAncestor(root.right,p,q)
        else:
            return root

2.8、872. 叶子相似的树

请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。
在这里插入图片描述
举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。
如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。
如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。
提示:
给定的两颗树可能会有 1 到 200 个结点。 给定的两颗树上的值介于 0 到 200 之间。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/leaf-similar-trees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:实际上是要求出叶子序列,然后比较两棵树的叶子序列是否相等的问题。一个遍历就可以求出叶子序列了,实际上还是遍历的应用。

简单框架:

vector<int> getLeafList(TreeNode* root); //遍历树的函数
bool leafSimilar(TreeNode* root1,TreeNode* root2){
	leafList1 = getLeafList(root1)
	leafList2 = getLeafList(root2)
	if(leafList1 == leafList2) return true;
	else return false;
}

题解代码(C++):

/**
 * 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:
    void traversal(TreeNode* root,vector<int> &res){
        if(root==NULL) return;
        if(root->left==NULL && root->right==NULL) res.push_back(root->val);
        traversal(root->left,res);
        traversal(root->right,res);
    }

    vector<int> getLeaf(TreeNode* root){
        vector<int> res;
        traversal(root,res);
        return res;
    }

    bool leafSimilar(TreeNode* root1, TreeNode* root2) {
        vector<int> v1 = getLeaf(root1);
        vector<int> v2 = getLeaf(root2);
        return v1==v2;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public void traversal(TreeNode root,List<Integer> res){
        if(root==null) return;
        if(root.left==null && root.right==null) res.add(root.val);
        traversal(root.left,res);
        traversal(root.right,res);
    }

    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        List<Integer> v1 = new ArrayList<Integer>();
        List<Integer> v2 = new ArrayList<Integer>();
        traversal(root1,v1);
        traversal(root2,v2);
        return v1.equals(v2);
    }
}

题解代码(Python):

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

class Solution:
    def traversal(self,root: TreeNode,res:List[int]):
        if root is None:
            return None
        if root.left is None and root.right is None:
            res.append(root.val)
        self.traversal(root.left,res)
        self.traversal(root.right,res)

    def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool:
        v1,v2 = [],[]
        self.traversal(root1,v1)
        self.traversal(root2,v2)
        return v1==v2

2.9、1022. 从根到叶的二进制数之和

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1
-> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
以 10^9 + 7 为模,返回这些数字之和。
示例:在这里插入图片描述
输入:[1,0,1,0,1,0,1] 输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
提示:
树中的结点数介于 1 和 1000 之间。 node.val 为 0 或 1 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-root-to-leaf-binary-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:本题和【2.6、257. 二叉树的所有路径】是类似的,都是同一个套路,只不过本题的值是组成一个二进制串,然后转换为十进制的数字,并且 以 109 + 7 为模,提示中有说到,节点数至多1000个,长达1000位的二进制数转为数字,肯定有溢出问题,所以答案要返回以 109 + 7 为模的结果。
(力扣很多题解上并没有注意这个问题,即使直接把结果都加到一个int变量上也没有溢出,可能是题目描述有问题。)

模运算与基本四则运算有些相似

  • (a + b) % p = (a % p + b % p) % p (1)
  • (a - b) % p = (a % p - b % p) %p (2)
  • (a * b) % p = (a % p * b % p) % p (3)
  • a ^ b % p = ((a % p)^b) %p (4)

题解代码(C++):

/**
 * 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:
    void dfs(TreeNode* root,int &sum,int pre)
    {
        if(root==NULL) return;
        pre = pre*2+root->val;
        if(root->left==NULL&&root->right==NULL)
            sum+=pre;
        dfs(root->left,sum,pre);
        dfs(root->right,sum,pre);
    }
    int sumRootToLeaf(TreeNode* root) {
          int sum=0;
          dfs(root,sum,0);
          return sum%1000000007;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int sum = 0;

    public void dfs(TreeNode root,int pre){
        if(root==null) return;
        pre=pre*2+root.val;
        if(root.left==null && root.right==null)
            this.sum+=pre;
        dfs(root.left,pre);
        dfs(root.right,pre);
    }

    public int sumRootToLeaf(TreeNode root) {
        this.sum = 0;
        dfs(root,0);
        return this.sum%1000000007;
    }
}

题解代码(Python):(Python int类型长度无限,不需要担心溢出问题)

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

class Solution:
    def __init__(self):
        self.total = 0

    def dfs(self,root:TreeNode,count:int) -> int:
        if root is None:
            return None
        count = count*2 + root.val
        if root.left is None and root.right is None:
            self.total += count
        self.dfs(root.left,count)
        self.dfs(root.right,count)

    def sumRootToLeaf(self, root: TreeNode) -> int:
        self.total = 0
        self.dfs(root,0)
        return self.total % (pow(10,9)+7)

2.10、538. 把二叉搜索树转换为累加树

给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater
Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
例如:
输入: 原始二叉搜索树:
在这里插入图片描述
输出: 转换为累加树:
在这里插入图片描述
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:
注意到又是二叉搜索树,是不是可能用到中序遍历?
以前的中序遍历框架:

void traversal(TreeNode* root){
	if(root==NULL) return;
	traversal(root->left);
	//中序遍历访问
	traversal(root->right);
}

回忆完毕,现在我们来看上面的遍历框架,如果是中序遍历,就可以输出升序的元素数组,那么现在我想要降序的呢?先输出然后再转置?这是一个方法。
那么如果改变一些框架的代码:

void traversal(TreeNode* root){
	if(root==NULL) return;
	traversal(root->right);
		//中序遍历访问
	traversal(root->left);
}

先遍历右子树,然后推导一遍,是不是输出了降序的数组呢?(自行验证)

现在是以降序的方向来遍历树了,降序累加,用数组的思维思考一下,就不难得到结果了。

题解代码(C++):

/**
 * 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:
    void dfs(TreeNode* root,int &sum){
        if(root==NULL) return;
        dfs(root->right,sum);
        root->val+=sum;//先改变为新值
        sum =root->val;//新值成为累加和
        dfs(root->left,sum);
    }
    TreeNode* convertBST(TreeNode* root) {
        int sum = 0;
        dfs(root,sum);
        return root;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int sum = 0;
    public void dfs(TreeNode root){
        if(root==null) return;
        dfs(root.right);
        root.val+=this.sum;
        this.sum= root.val;
        dfs(root.left);
    }
    public TreeNode convertBST(TreeNode root) {
        this.sum=0;
        dfs(root);
        return root;
    }
}

题解代码(Python):

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

class Solution:
    def __init__(self):
        self.temp = 0

    def dfs(self,root:TreeNode):
        if root is None:
            return None
        self.dfs(root.right)
        root.val+=self.temp
        self.temp = root.val
        self.dfs(root.left)

    def convertBST(self, root: TreeNode) -> TreeNode:
        self.temp = 0
        self.dfs(root)
        return root

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值