深度优先搜索的思想:一条路走到底,不撞南墙不回头
1、树的深度优先搜索遍历
(1) 二叉树的先序遍历
(2) 二叉树的中序遍历
(3) 二叉树的后序遍历
三种遍历方式的比较
(4)递归算法和非递归算算法的转化
力扣相关例题:
1、| 二叉树的最大深度 |
两行代码搞定:
class Solution {
public:
int maxDepth(TreeNode* root) {
if (!root) return 0; //递归的边界条件
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
//当root不空,返回左右子树高度的最大值+1
}
};
2、|二叉树的最小深度|
| |
这里需要注意题目的要求:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
如果直接将上题的max换成min是不对的,因为他返回的是左右子树的最小高度+1,而左右子树不一定存在,题目要求的是根节点到叶子节点的距离,所以对应的结点必须存在
那么分情况讨论即可:
对于一个节点而言,无非就是5种情况:空、叶子结点、有左右子树、有左子树、有右子树
class Solution {
public:
int minDepth(TreeNode* root) {
if (!root) return 0; //空节点
else if (!root->left && !root->right) return 1;//叶子结点
else if (root->left && root->right) return min(minDepth(root->left), minDepth(root->right)) + 1; //左右子树均不空
else if (root->left) return minDepth(root->left)+1; //只有左子树
else return minDepth(root->right)+1; //只有右子树
}
};
3、路径总和
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) return false; //空节点
else if (!root->left && !root->right) return root->val == targetSum; //叶子结点
else
return hasPathSum(root->left, targetSum-root->val) || hasPathSum(root->right, targetSum-root->val);
}
};
4、翻转二叉树
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (!root) return root;
TreeNode *left = invertTree(root->left);
TreeNode *right = invertTree(root->right);
root->right = left;
root->left = right;
return root;
}
};
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
return isSame(root->left, root->right);
}
bool isSame(TreeNode *p, TreeNode *q){
//判断p、q两棵子树是否对称
if (!p && !q) return true; //两棵子树均为空
else if (p && q) //两个子树均不空时,判断根节点是否相等、左右子树是否对称
return (p->val == q->val) && isSame(p->left, q->right) && isSame(p->right, q->left);
else return false;
}
};
class Solution {
private:
int res = 0;
public:
int sumNumbers(TreeNode* root) {
DFS(0, root);
return res;
}
void DFS(int last, TreeNode* root){//实际上是一个二叉树先序遍历的过程
//last表示到达root之前的数值
if (!root) return ;
last = last*10 + root->val;//这一步的位置很关键,如果直接放在上一行代码之前,会报错,因为root可能为空,root->val不存在
if (!root->left && !root->right) {
//递归出口是叶子结点,当到达叶子结点之后说明从根节点到当前的叶子结点已经可以构成一个数,让res += last
res += last;
return ;
}
DFS(last, root->left);
DFS(last, root->right);
}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || p == root || q == root) return root;//递归出口
TreeNode *left = lowestCommonAncestor(root->left, p, q);//在左子树上寻找最低公共祖先节点
TreeNode *right = lowestCommonAncestor(root->right, p, q);//在右子树上寻找
if (left && right) return root;
else if (!left && !right) return NULL;
else if (left) return left;
else return right;
}
};
class Solution {
private:
vector<int> preorder, inorder;
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
this->preorder = preorder;
this->inorder = inorder;
int n = preorder.size();
return build(0, n-1, 0, n-1);
}
TreeNode* build(int l1, int h1, int l2, int h2){
TreeNode *root= new TreeNode(preorder[l1]);
int i;
for (i = l2; preorder[l1] != inorder[i]; i++);
int llen = i-l2, rlen = h2-i;
if (llen){
root->left = build(l1+1, l1+llen, l2, l2+llen-1);
}
if (rlen){
root->right = build(h1-rlen+1, h1, h2-rlen+1, h2);
}
return root;
}
};
class Solution {
private:
vector<int> inorder, postorder;
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
this->postorder = postorder;
this->inorder = inorder;
int n = postorder.size();
return build(0, n-1, 0, n-1);
}
TreeNode* build(int l1, int h1, int l2, int h2){
TreeNode *root= new TreeNode(postorder[h2]);
int i;
for (i = l1; postorder[h2] != inorder[i]; i++);
int llen = i-l1, rlen = h1-i;
if (llen){
root->left = build(l1, l1+llen-1, l2, l2+llen-1);
}
if (rlen){
root->right = build(h1-rlen+1, h1, h2-rlen, h2-1);
}
return root;
}
};
10、前序遍历构造二叉搜索树
class Solution {
public:
TreeNode* bstFromPreorder(vector<int>& preorder) {
TreeNode* root = nullptr;
for (int x : preorder) insert(root, x);
return root;
}
void insert(TreeNode* &root, int x){
if (!root){
root = new TreeNode(x);
return ;
}
if (root->val > x) insert(root->left, x);
else if (root->val < x) insert(root->right, x);
}
};