《剑指Offer》模块2 二叉树【15道二叉树帮助你掌握二叉树】

二叉树

  • 二叉树
    • 1. 树中两个结点的最低公共祖先
        • 方法一:公共路径
        • 方法二:递归
    • 2. 重建二叉树
        • 根据前序遍历和中序遍历 得到树
      • 补充题:树的遍历
    • 3. 二叉树的下一个节点
    • 4. 树的子结构( 递归中调用递归 )
    • 5. 二叉树的镜像(两个指针互换可用 swap)
    • 6. 对称的二叉树
        • 错解:通过根节点比较子节点
        • 正解:比较当前节点的值即可
    • 7. 不分行从上往下打印二叉树( 层序遍历二叉树bfs )
    • 8. 分行从上往下打印二叉树
        • ( 利用两个队列遍历 )
        • 利用数组个数 进行遍历
    • 9. 之字形打印二叉树
    • 10. 二叉搜索树的后序遍历序列
        • 考点:根据二叉搜索树的后序遍历的特点
    • 11. 二叉树中和为某一值的路径( dfs回溯 )
        • 注意:只能是根节点到叶子节点
    • 12. 序列化二叉树【序列化二叉树(本质就是 前中后序遍历)】
    • 13. 二叉搜索树的第k个结点
    • 14. 二叉树的深度【二叉树递归】
    • 15. 平衡二叉树【二叉树递归】

二叉树

1. 树中两个结点的最低公共祖先

原题链接

在这里插入图片描述

方法一:公共路径

分别找出根节点到两个节点的路径,则最后一个公共节点就是最低公共祖先了。

时间复杂度分析:需要在树中查找节点,复杂度为O(n)

/*** 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:int findPath(TreeNode*root, TreeNode* p, vector<TreeNode*>&path){if(!root)return 0;if(root->val==p->val){path.push_back(root);return 1;}int l = findPath(root->left,p,path);int r = findPath(root->right,p,path);if(l==1||r==1)path.push_back(root);return l==1||r==1;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {vector<TreeNode*>path1,path2;findPath(root,p,path1);findPath(root,q,path2);if(path1.empty()||path2.empty())return NULL;TreeNode* res =NULL;for(int i = 0;i<path1.size();i++){if(i>=path1.size()||i>=path2.size())break;if(path1[path1.size()-1-i]==path2[path2.size()-1-i])res = path1[path1.size()-1-i];elsebreak;}return res;}
};

方法二:递归

考虑在左子树和右子树中查找这两个节点,如果两个节点分别位于左子树和右子树,则最低公共祖先为自己(root),若左子树中两个节点都找不到,说明最低公共祖先一定在右子树中,反之亦然。考虑到二叉树的递归特性,因此可以通过递归来求得。

时间复杂度分析:需要遍历树,复杂度为 O(n)

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(!root)return NULL;if(root==p||root==q)return root;TreeNode* left = lowestCommonAncestor(root->left, p, q);TreeNode* right = lowestCommonAncestor(root->right, p, q);if(left&&right)return root;if(left==NULL)return right;elsereturn left;}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public boolean flag = false;public TreeNode ans = null;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {dfs(root,p,q);return ans;}public TreeNode dfs(TreeNode root,TreeNode p,TreeNode q){if(root == null){return null;}TreeNode l = dfs(root.left,p,q);TreeNode r = dfs(root.right,p,q);if(l != null && r != null){ans = root;return ans;} else if((l != null || r != null) && (root.val == p.val || root.val == q.val)){ans = root;return ans;} else if(root.val == p.val && root.val == q.val) {ans = root;return ans;} else if(root.val == p.val || root.val == q.val) {return root;} else if((l != null || r != null)){return root;}return null;}}

2. 重建二叉树

原题链接

在这里插入图片描述

根据前序遍历和中序遍历 得到树

过程如下:

  1. 首先根据前序遍历找到 根节点
  2. 找到中序遍历中,该根节点的位置
  3. 中序中 位于 根节点左边的就是 左子树,右边的就是右子树
  4. 由于我们需要在中序遍历中找到根节点的位置,那么每次都需要遍历中序遍历,不如直接用unordered_map存储数值和位置
  5. 便于写代码,我们可以每次把mp[根节点] 的位置 用变量表示出来

在这里插入图片描述

本题的代码不需要死记硬背

就需要明白

由前序确定根节点
由中序确定左右子树的个数
由左右子树的个数确定下一个根节点的位置

根据这三点去写代码即可

/*** 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:unordered_map<int,int> pos;TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {int n = preorder.size();for (int i = 0; i < n; i ++ )pos[inorder[i]] = i;return dfs(preorder, inorder, 0, n - 1, 0, n - 1);}TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir){if (pl > pr) return NULL;int k = pos[pre[pl]] - il;TreeNode* root = new TreeNode(pre[pl]);root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);return root;}
};

补充题:树的遍历

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include<memory>
using namespace std;const  int N = 35;
int n;
int inorder[N], postorder[N];
unordered_map<int, int > leftChile, rightChile;//哈希表保存树,leftChile[i] = j: i 的左儿子是j,rightChilet同理
unordered_map<int, int > h;//保存中序遍历中各节点的位置int dfs(int postorder[], int inorder[], int l1, int r1, int l2, int r2)//构造二叉树
{   if (l1 > r1) return 0;//没有节点,返回0int root = postorder[r1];//根结点为后续遍历的最后一个节点int k = h[root];//找到根节点在序遍历中的位置leftChile[root] = dfs(postorder, inorder, l1, k - 1 - l2 + l1, l2, k - 1);//构造左儿子rightChile[root] = dfs(postorder, inorder,r1-1 - (r2 - (k +1)) , r1 -1, k + 1, r2);//构造右儿子return root;
}int main()
{cin >> n;//输入for (int i = 0; i < n; i++)cin >> postorder[i];for (int i = 0; i < n; i++){cin >> inorder[i];h[inorder[i]] = i;//保存中序遍历中各个节点的位置}int root = dfs(postorder, inorder, 0, n - 1, 0, n - 1);//构造二叉树//数组模拟队列int q[N], hh = 0, tt = -1;//按层次遍历if (root)//非0 表示有节点q[++tt] = root;while (hh <= tt){int t = q[hh++];if (leftChile[t]) q[++tt] = leftChile[t];//非0 为节点,入队列if (rightChile[t]) q[++tt] = rightChile[t];//非0 为节点,入队列}for (int i = 0; i <= tt; i++)//队列中保存的就是按层次遍历的结果cout << q[i] << " ";return 0;
}

3. 二叉树的下一个节点

原题链接

中序遍历:左根右

在这里插入图片描述

本题要分析节点的特点

  1. 如果节点有右子树,那么右子树的最左边的节点就是该节点后序
  2. 如果没有右子树,会有三种可能,在代码中有体现
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode father;*     TreeNode(int x) { val = x; }* }*/
class Solution {/*** 模拟* 时间复杂度:O(height),height 为二叉树的高度* 空间复杂度:O(1)*/public TreeNode inorderSuccessor(TreeNode p) {TreeNode node = p;// Case 1. 如果该节点有右子树,那么下一个节点就是其右子树中最左边的节点if (node.right != null) {node = node.right;while (node.left != null) {node = node.left;}return node;}if(node.father != null && node.father.left == node)return node.father;if(node.father != null && node.father == null)return null;while(node.father!=null && node.father.right == node){node = node.father;}return node.father;}
}

4. 树的子结构( 递归中调用递归 )

原题链接
在这里插入图片描述
在这里插入图片描述

/*** 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 hasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {if (!pRoot1 || !pRoot2) return false;if (isSame(pRoot1, pRoot2)) return true;return hasSubtree(pRoot1->left, pRoot2) || hasSubtree(pRoot1->right, pRoot2);}bool isSame(TreeNode* pRoot1, TreeNode* pRoot2) {if (!pRoot2) return true;if (!pRoot1 || pRoot1->val != pRoot2->val) return false;return isSame(pRoot1->left, pRoot2->left) && isSame(pRoot1->right, pRoot2->right);}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public boolean hasSubtree(TreeNode pRoot1, TreeNode pRoot2) {// 类比字符串匹配if (pRoot1 == null || pRoot2 == null) return false;if (isPart(pRoot1, pRoot2)) return true;// 如果以 pRoot1 开始的子树不能包含 pRoot2 的话,就从 pRoot1.left 和 pRoot1.right 开始return hasSubtree(pRoot1.left, pRoot2) || hasSubtree(pRoot1.right, pRoot2);}// 以 pRoot1 节点为根的情况下,pRoot1 和 pRoot2 同时对应遍历,如果遍历到的值都相同,且 pRoot2 先遍历到 null 或者同时遍历到 null,说明 pRoot2 是 pRoot1 的子结构public boolean isPart(TreeNode pRoot1, TreeNode pRoot2) {if (pRoot2 == null) return true;if (pRoot1 == null || pRoot1.val != pRoot2.val) return false;// 同时遍历左右子树return isPart(pRoot1.left, pRoot2.left) && isPart(pRoot1.right, pRoot2.right);}
}

5. 二叉树的镜像(两个指针互换可用 swap)

原题链接
在这里插入图片描述
在这里插入图片描述

/*** 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 mirror(TreeNode* root) {if (!root) return;swap(root->left, root->right);mirror(root->left);mirror(root->right);}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public void mirror(TreeNode root) {dfs(root);}public void dfs(TreeNode root){if(root == null){return;}TreeNode temp = root.right;root.right = root.left;root.left = temp;dfs(root.left);dfs(root.right);}}

6. 对称的二叉树

原题链接
在这里插入图片描述
在这里插入图片描述

错解:通过根节点比较子节点

没写完,太复杂

/*** 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 isSymmetric(TreeNode* root) {if(root == NULL)return true;return dfs(root->left,root->right);}bool dfs(TreeNode* r1,TreeNode* r2){if(r1==NULL && r2==NULL)return true;if(r1!=NULL&&r2==NULL || r1==NULL&&r2!=NULL)return false;if(r1->left->val != r2->right->val || r1->right->val != r2->left->val)return false;return dfs(r1->left,r2->right) && dfs(r1->right,r2->left);}};

正解:比较当前节点的值即可

/*** 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 isSymmetric(TreeNode* root) {if(root == NULL)return true;return dfs(root->left,root->right);}bool dfs(TreeNode* r1,TreeNode* r2){if(r1==NULL && r2==NULL)return true;if(r1!=NULL&&r2==NULL || r1==NULL&&r2!=NULL)return false;if(r1->val != r2->val)return false;return dfs(r1->left,r2->right) && dfs(r1->right,r2->left);}};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public boolean isSymmetric(TreeNode root) {if(root == null){return true;}return dfs(root.left,root.right);}public boolean dfs(TreeNode l,TreeNode r){if((l == null && r != null) || (l != null && r == null)){return false;}if(l == null && r == null){return true;}if(l.val != r.val){return false;}return dfs(l.left,r.right) && dfs(l.right,r.left);}}

7. 不分行从上往下打印二叉树( 层序遍历二叉树bfs )

原题链接

在这里插入图片描述

/*** 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<int> printFromTopToBottom(TreeNode* root) {vector<int> ans;if(root==NULL)return ans;queue<TreeNode*> q;q.push(root);while(q.size()){auto t = q.front();q.pop();ans.push_back(t->val);if(t->left != NULL)q.push(t->left);if(t->right != NULL)q.push(t->right);}return ans;}
};

8. 分行从上往下打印二叉树

( 利用两个队列遍历 )

利用数组个数 进行遍历

原题链接

在这里插入图片描述
在这里插入图片描述

/*** 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<int> get_val(vector<TreeNode*> level){vector<int> res;for (auto &u : level)res.push_back(u->val);return res;}vector<vector<int>> printFromTopToBottom(TreeNode* root) {vector<vector<int>>res;if (!root) return res;vector<TreeNode*>level;level.push_back(root);res.push_back(get_val(level));while (true){vector<TreeNode*> newLevel;for (auto &u : level){if (u->left) newLevel.push_back(u->left);if (u->right) newLevel.push_back(u->right);}if (newLevel.size()){res.push_back(get_val(newLevel));level = newLevel;}else break;}return res;}
};

9. 之字形打印二叉树

原题链接
在这里插入图片描述
本题和上一道题差不多
就是需要定义一个变量
判断是否需要翻转

/*** 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<int> get_val(vector<TreeNode*> level){vector<int> res;for (auto &u : level)res.push_back(u->val);return res;}vector<vector<int>> printFromTopToBottom(TreeNode* root) {vector<vector<int>>res;if (!root) return res;vector<TreeNode*>level;level.push_back(root);res.push_back(get_val(level));bool zigzag = true;while (true){vector<TreeNode*> newLevel;for (auto &u : level){if (u->left) newLevel.push_back(u->left);if (u->right) newLevel.push_back(u->right);}if (newLevel.size()){vector<int>temp = get_val(newLevel);if (zigzag)reverse(temp.begin(), temp.end());res.push_back(temp);level = newLevel;}else break;zigzag = !zigzag;}return res;}
};
/*** 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>> printFromTopToBottom(TreeNode root) {List<List<Integer>> ans = new ArrayList<>();if(root == null){return ans;}Queue<TreeNode> q1 = new LinkedList<TreeNode>();q1.offer(root);List<Integer> l = new ArrayList();l.add(root.val);ans.add(l);boolean flag = false;while(true) {Queue<TreeNode> q2 = new LinkedList<TreeNode>();for(TreeNode x : q1){if(x.left != null) {q2.offer(x.left);}if(x.right != null) {q2.offer(x.right);}}if(!q2.isEmpty()) {List<Integer> l1 = new ArrayList();for(TreeNode x : q2){l1.add(x.val);}if(flag == false){Collections.reverse(l1);flag = true;} else {flag = false;}ans.add(l1);q1 = q2;} else {break;}}return ans;}
}
```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>> printFromTopToBottom(TreeNode root) {List<List<Integer>> ans = new ArrayList<>();if(root == null){return ans;}Queue<TreeNode> q1 = new LinkedList<TreeNode>();q1.offer(root);List<Integer> l = new ArrayList();l.add(root.val);ans.add(l);while(true) {Queue<TreeNode> q2 = new LinkedList<TreeNode>();for(TreeNode x : q1){if(x.left != null) {q2.offer(x.left);}if(x.right != null) {q2.offer(x.right);}}if(!q2.isEmpty()) {List<Integer> l1 = new ArrayList();for(TreeNode x : q2){l1.add(x.val);}ans.add(l1);q1 = q2;} else {break;}}return ans;}
}

10. 二叉搜索树的后序遍历序列

原题链接
在这里插入图片描述

考点:根据二叉搜索树的后序遍历的特点

由于是后序遍历,所以最后一个结点就是根节点,又因为是二叉搜索树,所以从第一个结点开始所有比它小的结点就是它的左子树,其他就是它的右子树。如果右子树有点不大于根节点的话就说明不是一棵二叉搜索树,返回false。最后递归处理左右子树。


class Solution {
public:vector<int> seq;//设成全局变量方便操作bool verifySequenceOfBST(vector<int> sequence) {seq = sequence;return dfs(0, seq.size() - 1);}bool dfs(int l, int r){//如果区间内啥也没有就说明把所有的结点都判断完了,却没有一个是有问题的,所以返回trueif (l >= r)return true;//取出根节点int root = seq[r];//找出所有从l开始连续的比根节点小的结点int k = l;while (k < r && seq[k] < root)k ++;//这时k就是右子树后序遍历中的第一个结点//如果不满足二叉搜索树的性质就返回falsefor (int i = k; i < r; i ++)if (seq[i] < root)return false;//递归处理左右子树//y总的视频里的代码是错的//他写的是return dfs(l, k - 1) && dfs(k + 1, r);//这样会WAreturn dfs(l, k - 1) && dfs(k, r - 1);}
};
class Solution {public boolean verifySequenceOfBST(int [] sequence) {seq = sequence;return dfs(0, seq.length - 1);}private boolean dfs(int l, int r) {if (l >= r) return true;int root = seq[r];int k = l;while (k < r && seq[k] < root) k++;for (int i = k; i < r; i++) {if (seq[i] < root)return false;}return dfs(l, k - 1) && dfs(k, r - 1);}private int[] seq;
}

11. 二叉树中和为某一值的路径( dfs回溯 )

注意:只能是根节点到叶子节点

原题链接
在这里插入图片描述
首先补充题意:本题要求的路径是根节点到叶子节点

本题就是一个dfs回溯问题

/*** 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>> ans;vector<vector<int>> findPath(TreeNode* root, int sum) {vector<int> sup;dfs(root,sum,sup);return ans;}void dfs(TreeNode* root,int sum,vector<int>& sup){if(root == NULL)return;sum -= root->val;sup.push_back(root->val);if(root->left == NULL && root->right == NULL && sum == 0)ans.push_back(sup);dfs(root->left,sum,sup);dfs(root->right,sum,sup);sum += root->val;sup.pop_back();}};
 * 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>> res = new ArrayList<>();public List<List<Integer>> findPath(TreeNode root, int sum) {List<Integer> list = new ArrayList<>();dfs(root,list,sum,0);return res;}void dfs(TreeNode root,List<Integer> list,int sum,int ans){if(root == null){return;}list.add(root.val);if(ans+root.val == sum && root.left == null && root.right == null){res.add(new ArrayList<>(list));}dfs(root.left,list,sum,ans+root.val);dfs(root.right,list,sum,ans+root.val);list.remove(list.size() - 1);}
}

12. 序列化二叉树【序列化二叉树(本质就是 前中后序遍历)】

原题链接
在这里插入图片描述
本题就是实现两个函数

把二叉树转成 字符串形式(可以根据前序遍历 后序遍历 中序遍历 层序遍历都可以)

然后把二叉树的字符串形式 转成二叉树

前序遍历:

/*** 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:// Encodes a tree to a single string.string serialize(TreeNode* root) {string res;dfs_s(root, res);return res;}void dfs_s(TreeNode *root, string &res){if (!root) {res += "null ";return;}res += to_string(root->val) + ' ';//int转成string就是用to_stringdfs_s(root->left, res);dfs_s(root->right, res);}// Decodes your encoded data to tree.TreeNode* deserialize(string data) {int u = 0;return dfs_d(data, u);}TreeNode* dfs_d(string data, int &u){if (u == data.size()) return NULL;int k = u;while (data[k] != ' ') k ++ ;if (data[u] == 'n') {u = k + 1;return NULL;}int val = 0, sign = 1;if (u < k && data[u] == '-') sign = -1, u ++ ;for (int i = u; i < k; i ++ ) val = val * 10 + data[i] - '0';val *= sign;u = k + 1;auto root = new TreeNode(val);root->left = dfs_d(data, u);root->right = dfs_d(data, u);return root;}
};

13. 二叉搜索树的第k个结点

原题链接

在这里插入图片描述

/*** 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 *ans;TreeNode* kthNode(TreeNode* root, int k) {dfs(root, k);return ans;}void dfs(TreeNode *root, int &k){if (!k || !root) return;dfs(root->left, k);--k;if (!k) ans = root;else dfs(root->right, k);}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public int k;public TreeNode kthNode(TreeNode root, int kk) {if(root == null){return null;}k = kk;return dfs(root);}public TreeNode dfs(TreeNode root){if(root == null || k < 0){return null;}TreeNode l = dfs(root.left);k = k - 1;if(k == 0){return root;}TreeNode r = dfs(root.right);if(l != null) {return l;} else if(r != null) {return r;} else {return null;}}
}

14. 二叉树的深度【二叉树递归】

原题链接
在这里插入图片描述

/*** 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:int treeDepth(TreeNode* root) {return dfs(root,0);}int dfs(TreeNode* r,int ans){if(r==NULL)return ans;ans++;return max(dfs(r->left,ans),dfs(r->right,ans));}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public int treeDepth(TreeNode root) {return dfs(root,0);}public int dfs(TreeNode root,int cnt) {if (root == null) {return cnt;}int l = dfs(root.left,cnt+1);int r = dfs(root.right,cnt+1);if (l > r) {return l;} else {return r;}}}

15. 平衡二叉树【二叉树递归】

原题链接
在这里插入图片描述

/*** 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 ans = true;bool isBalanced(TreeNode* root) {dfs(root);return ans;}int dfs(TreeNode *root){if (!root) return 0;int left = dfs(root->left), right = dfs(root->right);if (abs(left - right) > 1) ans = false;return max(left, right) + 1;}
};
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {boolean flag = true;public boolean isBalanced(TreeNode root) {dfs(root,0);return flag;}public int dfs(TreeNode root,int cnt) {if (root == null) {return cnt;}int l = dfs(root.left,cnt+1);int r = dfs(root.right,cnt+1);if (l - r >= 2) {flag = false;}if (l > r) {return l; } else {return r;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1549700.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

win7桌面图标突然消失,鼠标右键不管用―解决

win7电脑桌面图标突然消失&#xff0c;鼠标右键不管用–解决 我的电脑是win7&#xff0c;当时正在下软件&#xff0c;快下完的时候突然桌面上的图标都没了&#xff0c;只剩一张桌面壁纸&#xff0c;鼠标右键没用&#xff0c;关机重启也不行&#xff0c;去网上查了拼拼凑凑终于…

win7桌面图标不可读文件样式的东西遮挡

win7桌面图标不可读文件样式的东西遮挡 解决方法 1&#xff1a; 右击桌面空白处&#xff0c;打开“个性化”设置&#xff0c;更改Windows主题&#xff0c;让系统重新加载快捷方式图标&#xff1b; 2&#xff1a; 打开路径C:\Users\你的用户名\AppData\Local&#xff0c;找到其中…

简述计算机网络系统图标添加在桌面上的步骤,如何将网络图标添加到win7桌面上...

win7网上邻居在哪&#xff1f;相信对于一些刚从WinXP升级到win7的盆友来说&#xff0c;对win7这款操作系统都不是特别的了&#xff0c;以致许多的盆友都都无法找到网上邻居&#xff0c;那么那么网上邻居在哪呢&#xff0c;下面小编就来为大家揭晓一下哈~ 方法一、 1、最简单的方…

win7变成xp风格了怎么改回_win7桌面怎么改成xp风格

随着win7系统不断发展和稳定&#xff0c;许多用户都从xp系统升级到win7系统&#xff0c;可是一些用户反馈说win7功能虽然多&#xff0c;但是界面不习惯&#xff0c;很多设置都不知道如何操作&#xff0c;和xp界面有很大不同。有什么办法可以让win7桌面改成xp风格&#xff1f;方…

怎样固定计算机桌面背景,Win7桌面背景老是被修改如何将其锁定不让他人随意修改...

网友提问&#xff1a;有时候桌面老是被人乱改&#xff0c;有没有办法能够让别人改不了桌面背景?使用的是深度技术Win7旗舰版系统。 墨染暖心解答&#xff1a;可以利用Win7系统注册表来锁定桌面背景&#xff0c;从而解决桌面背景被修改的问题。 具体操作步骤如下&#xff1a; 1…

计算机桌面无法新建文件夹,Win7桌面不能新建文件夹和修改文件名怎么办?

在Win7系统中&#xff0c;用户为了方便查看文件喜欢在桌面上创建文件夹&#xff0c;但是不少用户会遇到这个问题&#xff1a;在Win7桌面不能新建文件夹&#xff0c;也无法修改文件名&#xff0c;系统弹出目标文件夹访问被拒绝的窗口&#xff0c;提示需要权限来执行操作&#xf…

win7桌面运行html,win7系统多桌面切换的解决方案

win7系统使用久了&#xff0c;好多网友反馈说win7系统多桌面切换的问题&#xff0c;非常不方便。有什么办法可以永久解决win7系统多桌面切换的问题&#xff0c;面对win7系统多桌面切换的图文步骤非常简单&#xff0c;只需要1.在电脑桌面任务栏左侧&#xff0c;点击“task view”…

计算机桌面黑底怎么弄,win7怎么设置桌面背景 win7桌面背景变成黑色问题

现在很多电脑用户都会设置个性化的桌面背景&#xff0c;现在各种精美的壁纸非常多&#xff0c;如果我们想要设置桌面背景的话怎么设置呢?方法很简单&#xff0c;下面小编为大家带来win7设置桌面背景的步骤教程&#xff0c;不知道怎么设置的朋友可以参照下面的步骤设置自己喜欢…

STM32之MPU6050获取欧拉角

STM32之MPU6050获取欧拉角 MPU6050MPU6050特点MPU6050电路图以及框图MPU6050框图MPU6050电路图 MPU6050相关寄存器电源管理寄存器1&#xff08;0x6B&#xff09;陀螺仪配置寄存器&#xff08;0x1B&#xff09;加速度计配置寄存器&#xff08;0x1C&#xff09;陀螺仪采样率分频寄…

欧拉角与RPY与旋转矩阵的测试

指定欧拉角&#xff0c;是指按照指定的顺序&#xff0c;按照右乘的方式构建旋转矩阵。 验证一&#xff1a;指定旋转矩阵&#xff0c;得到欧拉角&#xff0c;按照轴角的方式重新构建矩阵&#xff1a; ///---------------------------//Eigen::Matrix3d rot_cl;rot_cl<<-…

Gimbal Lock欧拉角死锁问题

技术背景 在前面几篇跟SETTLE约束算法相关的文章(1, 2, 3)中&#xff0c;都涉及到了大量的向量旋转的问题--通过一个旋转矩阵&#xff0c;给定三个空间上的欧拉角\(\alpha, \beta, \gamma\)&#xff0c;将指定的向量绕对应轴进行旋转操作。而本文主要就阐述这些旋转操作中&…

四元数与欧拉角之间的转换

在3D图形学中&#xff0c;最常用的旋转表示方法便是四元数和欧拉角&#xff0c;比起矩阵来具有节省存储空间和方便插值的优点。本文主要归纳了两种表达方式的转换&#xff0c;计算公式采用3D笛卡尔坐标系&#xff1a; 图1 3D Cartesian coordinate System (from wikipedia) 定义…

欧拉角、旋转矩阵及四元数

欧拉角、旋转矩阵及四元数 1. 简介2. 欧拉角2.1 欧拉角定义2.2 右手系和左手系2.3 转换流程 3. 旋转矩阵4. 四元数4.1 四元数与欧拉角和旋转矩阵之间等效变换4.2 测试Matlab代码 5. 总结 1. 简介 常用姿态参数表达方式包括方向余弦矩阵、欧拉轴/角参数、欧拉角、四元数以及罗德…

欧拉角物理含义

欧拉角定义 欧拉角与方向余弦矩阵以一对应 方向余弦矩阵与欧拉角存在一一对应关系。当已知欧拉角&#xff0c;规定了每次旋转的轴&#xff08;XYZ&#xff09;和每次旋转的角度&#xff0c;就可以得到方向余弦矩阵。 想想方向余弦矩阵是如何得到的&#xff1f;通过三个二维方向…

欧拉角表示的旋转相乘计算

在Eigen中用欧拉角表示旋转时&#xff0c;单次旋转多个角度和多次旋转单个角度的结果是不同的。具体试验如下&#xff1a; 在VS2017中用Eigen分别初始化两个欧拉角旋转&#xff1a; 第一个&#xff1a;欧拉角旋转为&#xff08;M_PI / 2, 0, M_PI / 4&#xff09; Eigen::Ve…

动态欧拉角与静态欧拉角的区别

看了网上好多的讲解,讲的都不是特别清晰,让人有一种很懵懵的感觉,感觉懂了,又貌似没懂的奇怪感觉,读了那么多的水文,大多都是内容差不多,好多文章之中错误百出,都是稍微提了一点,没有详细对比二者的区别,很难让人从心里真正明白其中含义.由于项目需要,这里对于动态欧拉角和静态…

旋转矩阵、欧拉角

旋转矩阵、欧拉角 注&#xff1a;下面为学习空间机器人技术系列课程笔记&#xff0c;加上一些自己的整理&#xff0c;方便复习。 一、旋转矩阵的引出 下面坐标系0的基向量为 ( x 0 &#xff0c; y 0 ) (x_{0}&#xff0c;y_{0}) (x0​&#xff0c;y0​)&#xff0c;坐标系1的基…

对于双欧拉角(正反欧拉角)的一些理解和思考

文章目录 一、正反欧拉角定义二、相关文献阐述三、对正反欧拉角的思考四、参考代码五、参考文献 最近看到有人讨论“双欧拉角”或者“正反欧拉角”的问题&#xff0c;因为自己之前没听说过这个概念&#xff0c;为了避免无知&#xff0c;因此找了一些文献进行学习和理解。不过基…

matlab 欧拉角 方向余弦,旋转矩阵、欧拉角之间转换

学习过程中涉及欧拉角和旋转矩阵的转换,索性整理学习一下欧拉角四元数和旋转矩阵的概念以及matlab中的互相转换 本文摘自各大课本,博客,自己学习整理使用,侵删 MATLAB矩阵乘法从左到右依次相乘 用R表示旋转矩阵。 yaw(偏航) pitch(俯仰) roll(横滚)分别表示Z Y X轴的转…

欧拉角旋转

欧拉角是一种表示三维旋转的描述方法&#xff0c;欧拉角的计算需要借助旋转矩阵&#xff0c;关于旋转矩阵的知识可先参考之前的文章&#xff1a;3维旋转矩阵推导与助记 欧拉角旋转 静态定义 对于在三维空间里的一个参考系&#xff0c;任何坐标系的取向&#xff0c;都可以用三…