110.平衡二叉树 (优先掌握递归)
使用后序遍历,只有判断左右子树的高度差才能得到当前节点代表的二叉树是不是平衡二叉树。
递归三部曲:
- 确定递归函数的参数和返回值:node,返回值高度(如果左右子树高度差大于1说明不是平衡二叉树就返回-1)
- 确定终止条件:node==null return 0
- 确定单层递归的逻辑:先判断左右子树高度有没有-1,有的话直接传给上一个节点也就是return -1,没有的话就计算左右子树的高度差判断是否高度差大于1,大于1就return -1,否则就return 最大高度
下面是C++,JAVA,Python代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getheight(TreeNode* node){
if(node==NULL) return 0;
int leftheight = getheight(node->left);
if(leftheight==-1) return -1;
int rightheight = getheight(node->right);
if(rightheight==-1) return -1;
int result;
if(abs(rightheight-leftheight)>1) result=-1;
else result = 1 + max(rightheight,leftheight);
return result;
}
bool isBalanced(TreeNode* root) {
int height = getheight(root);
if(height==-1) return false;
else return true;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int getheight(TreeNode node){
if(node==null) return 0;
int leftheight = getheight(node.left);
if(leftheight==-1) return -1;
int rightheight = getheight(node.right);
if(rightheight==-1) return -1;
int result;
if(Math.abs(rightheight-leftheight)>1) return -1;
else result = 1+ Math.max(rightheight, leftheight);
return result;
}
public boolean isBalanced(TreeNode root) {
int height = getheight(root);
if(height==-1) return false;
else return true;
}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def getheight(self, node):
if(node==None):
return 0
leftheight = self.getheight(node.left)
if leftheight==-1:
return -1
rightheight = self.getheight(node.right)
if rightheight==-1:
return -1
if abs(rightheight-leftheight)>1:
return -1
return (1+max(rightheight,leftheight))
def isBalanced(self, root):
"""
:type root: Optional[TreeNode]
:rtype: bool
"""
height = self.getheight(root)
if height==-1:
return False
return True
参考文章
257. 二叉树的所有路径 (优先掌握递归)
使用前序遍历,因为只有前序遍历才能让父节点指向孩子节点。
第一次接触回溯算法。path在其中是保存当前处理的路径的。
下图是一个示意图。其中1,2… 14是递归和回溯的路径。
它的大体意思是说我递归得到了6->4->3之后,我只有pop了3回溯到4节点才能得到6->4->1这个路径。同理,我只有pop了1,然后pop了4回溯到6才能找到6->7->8这个路径。
下面是C++, JAVA,Python代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
void traversal(TreeNode* cur, vector<int>& path, vector<string>& result){
path.push_back(cur->val);//中为什么写在这里,因为终止条件是叶子节点,如果写在终止条件的下面就布恩那个吧叶子节点保存了
//这才到叶子节点
if(cur->left==NULL && cur->right==NULL){
string sPath;
for(int i=0; i<path.size()-1;i++){
sPath += to_string(path[i]);//把节点放入
sPath += "->";
}
sPath += to_string(path[path.size()-1]);
result.push_back(sPath);//把当前路径加入到最后结果中
return;
}
if(cur->left){
traversal(cur->left, path, result);
path.pop_back();//回溯
}
if(cur->right){//右
traversal(cur->right, path, result);
path.pop_back();//回溯
}
}
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
if(root==NULL) return result;
traversal(root, path, result);
return result;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();//最终的结果
if(root == null){
return res;
}
List<Integer> paths = new ArrayList<>();//作为结果中的路径
traversal(root, paths, res);
return res;
}
private void traversal(TreeNode root, List<Integer> paths, List<String> res){
paths.add(root.val);//往路径中添加节点
//遇到叶子节点
if(root.left==null && root.right==null){
//输出
StringBuilder sb = new StringBuilder();//创建一个StringBuilder用来拼接字符,速度更快。
for(int i = 0; i < paths.size() -1 ; i++){
sb.append(paths.get(i)).append("->");//
}
sb.append(paths.get(paths.size()-1));//记录最后一个节点
res.add(sb.toString());//收集到一个路径
return;
}
//递归和回溯同时进行
if(root.left != null){//左
traversal(root.left, paths, res);
paths.remove(paths.size() - 1);//回溯
}
if(root.right != null){//右
traversal(root.right, paths, res);
paths.remove(paths.size() - 1);
}
}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def binaryTreePaths(self, root):
"""
:type root: Optional[TreeNode]
:rtype: List[str]
"""
result = []
path = []#记录当前这条路径的
if not root:
return result#空节点
self.traversal(root, path, result)
return result
def traversal(self, cur, path, result):
path.append(cur.val)#中
if not cur.left and not cur.right:#说明到达叶子节点
sPath = '->'.join(map(str, path))
result.append(sPath)
return
if cur.left:#左
self.traversal(cur.left, path, result)
path.pop() #我是不是可以理解为每个节点它执行完左孩子然后pop出来,再对右孩子进行操作,当然真实的递归很多层,递归-回溯同时进行
if cur.right:#右
self.traversal(cur.right, path, result)
path.pop()
参考文章
404.左叶子之和 (优先掌握递归)
使用后序遍历。(其他也可以,后序代码简洁)
明确左叶子的定义:1. 必须是叶子节点 2. 是它父节点的左孩子
递归到叶子节点的时候是无法判断当前这个叶子节点是左叶子还是右叶子,所以只能在叶子节点的父节点进行判断。
所以递归的时候只处理到叶子节点的父节点,或者说遍历到当前节点的时候计算当前节点的左右子树的左叶子之和。
C++,JAVA和Python代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
//如果节点为空返回为0
if(root == NULL) return 0;
//如果节点是叶子节点也返回0,因为只处理到叶子节点的父节点
if(root->left == NULL && root->right == NULL) return 0;
//计算左子树,如果左子树只包含一个节点就是左叶子,就将leftnum赋值为这个左叶子的值
int leftNum = sumOfLeftLeaves(root->left);//如果root->left是叶子节点他进入函数就是处理夜子姐带你的逻辑返回是0,下面是复制为root.val不冲突
if(root->left!=NULL && root->left->left==NULL && root->left->right==NULL){
leftNum = root->left->val;
}
int rightNum = sumOfLeftLeaves(root->right);
int sum = leftNum + rightNum;//当前节点的左叶子之和就是当前节点的左子树和左叶子之和加上右子树的左叶子之和
return sum;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null) return 0;
if(root.left==null && root.right==null) return 0;
int leftNum = sumOfLeftLeaves(root.left);
if(root.left!=null && root.left.left==null && root.left.right==null){
leftNum = root.left.val;
}
int rightNum = sumOfLeftLeaves(root.right);
int sum = leftNum+rightNum;
return sum;
}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def sumOfLeftLeaves(self, root):
"""
:type root: Optional[TreeNode]
:rtype: int
"""
if root == None:
return 0
if root.left==None and root.right==None:
return 0
leftNum = self.sumOfLeftLeaves(root.left)
if root.left != None and root.left.left==None and root.left.right==None:
leftNum = root.left.val
rightNum = self.sumOfLeftLeaves(root.right)
sum_ = leftNum + rightNum
return sum_
参考文章
222.完全二叉树的节点个数(优先掌握递归)
一种是按照后序遍历的模板写,时间复杂度是O(n)
一种是按照完全二叉树的定义来写.
完全二叉树的叶子节点是顺序排列的,所以完全二叉树你可以认为它是由多个满二叉树组成的,一个节点是最小的满二叉树.
下面是C++,JAVA和Python的代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int countNodes(TreeNode* root) {
if(root==NULL) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftdepth = 0;
int rightdepth = 0;
while(left){
left = left->left;
leftdepth++;
}
while(right){
right = right->right;
rightdepth++;
}
if(leftdepth==rightdepth){
return (2<<leftdepth)-1;//2 = 2^1,所以使用2<<leftdepth==1<<(leftdepth+1),这里初始化的时候是使用的leftdepth=0所以这个是2
}
int leftnum = countNodes(root->left);
int rightnum = countNodes(root->right);
int result = leftnum+rightnum+1;
return result;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
if(root==null) return 0;
TreeNode left = root.left;
TreeNode right = root.right;
int leftdepth = 0; int rightdepth = 0;
while(left!=null){
left = left.left;
leftdepth++;
}
while(right!=null){
right = right.right;
rightdepth++;
}
if(leftdepth==rightdepth){
return (2<<leftdepth)-1;
}
int leftnum = countNodes(root.left);
int rightnum = countNodes(root.right);
int result = leftnum+rightnum+1;
return result;
}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def countNodes(self, root):
"""
:type root: Optional[TreeNode]
:rtype: int
"""
if root == None:
return 0
left = root.left
right = root.right
leftdepth =0
rightdepth = 0
while(left):
left = left.left
leftdepth+=1
while(right):
right = right.right
rightdepth+=1
if leftdepth == rightdepth:
return (2<<leftdepth)-1
leftnum = self.countNodes(root.left)
rightnum = self.countNodes(root.right)
result = leftnum+rightnum+1
return result