深度优先搜索DFS

深度优先搜索的思想:一条路走到底,不撞南墙不回头
在这里插入图片描述

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;
    }
};

5、相同的树
对称二叉树

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;
    }
};

6、求根节点到叶节点数字之和

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);
    }
};

7、二叉树的最近公共祖先

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;    
    }
};

8、根据前序和后序遍历构造二叉树

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;
    }
};

9、从中序与后序遍历序列构造二叉树

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);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值