leetcode 经典二叉树算法题目(思路、方法、code)

本文详细解析了leetcode中经典的二叉树算法题目,包括翻转二叉树、路径总和、路径总和 II、最近公共祖先等,通过递归和迭代方法阐述解题思路,帮助理解二叉树的各种遍历方式。
摘要由CSDN通过智能技术生成

leetcode 经典二叉树算法题目(思路、方法、code)

二叉树相关题目,主要就是要搞定二叉树的多种遍历方式,包括先序遍历,中序遍历,后序遍历,层次遍历,DFS遍历。掌握了所有的遍历方法,二叉树的题目基本就化简为一些简单问题去解决。
二叉树由于其良好的结构,很多题目都可以化为递归去解决。


二叉树的常用结构体定义:

 struct TreeNode {
   
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {
   }
 };
226. 翻转二叉树

翻转一棵二叉树。

示例:
输入:
         4
       /   \
      2     7
     / \   / \
    1   3 6   9
输出:
   	    4
  	  /   \
 	 7     2
 	/ \   / \
	9   6 3   1

分析:翻转二叉树是非常经典的一个问题。

方法一:递归

  • 如果一个树是空的,则翻转的结果仍为空
  • 如果一个树非空,则翻转的结果应该为,翻转后的树的左子树应该是原来右子树经过翻转得到的,翻转后的树的右子树应该是右原来的左子树翻转得到的
  • 根据该递归规则进行递归即可
class Solution {
   
public:
    TreeNode* invertTree(TreeNode* root) {
   
        if(root==NULL) return NULL;
        TreeNode* temp=root->left; //注意需要一个中间变量
        root->left=invertTree(root->right);//这里左子树将发生变化,故之前需要中间变量保存下来原来的左子树
        root->right=invertTree(temp);
        return root;
    }
};

方法二:迭代

迭代法的主要思想是,我们需要遍历树中所有节点,然后将每个节点的两个子树进行调换。可以用BFS的方法遍历树中节点,并将未访问的节点存放在queue中,也可以用先序遍历等(但非递归地遍历还是BFS比较容易写)

class Solution {
   
public:
    TreeNode* invertTree(TreeNode* root) {
   
        if(root==NULL) return NULL;
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()) //队列非空则一直进行 
        {
   
			TreeNode* first=queue.front(); 
			TreeNode* temp=first->left;  //交换左右子树
			first->left=first->right;
			first->right=temp;
			if(first->left!=NULL) queue.push(first->left); //子树非空则添加进队列
			if(first->right!=NULL) queue.push(first->right);
			queue.pop();  //将队列头pop出去
		} 
		return root;
    }
};
112. 路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例: 
给定如下二叉树,以及目标和 sum = 225
         / \
        4   8
       /   / \
      11  13  4
     /  \      \
    7    2      1
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2

分析:解决该问题,我们需要知道,如何将问题化为子问题,如何判断一个节点是叶节点,当遍历到叶节点时如何判断。

两个子树都为空,则为叶结点。 如果是递归处理该问题,则主要判断当前的值是否与sum一致即可。

  • 如果该节点为空,则返回false
  • 否则判断该节点的是否是叶子节点,如果是叶子节点并且该值等于sum,则返回true
  • 否则向下遍历,等于两个子节点对该问题的,当然子问题处理时 s u m − v a l sum-val sumval,
class Solution {
   
public:
    bool is_leaf(TreeNode* root)
    {
   
        if(root->left==NULL&&root->right==NULL)
            return true;
        else
            return false;
    }
    bool hasPathSum(TreeNode* root, int sum) 
    {
   
        if(root==NULL) return false;
        if(root->left==NULL&&root->right==NULL&&root->val==sum)  //是叶节点并且值为sum,则返回true
            return true;
        return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val);
    }
};
113. 路径总和 II

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 225
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

分析:该问题需要给出路径,因此回溯法是非常可行的一种方法。

leetcode 经典回溯算法题目(思路、方法、code)

用回溯法经典套路:

  • 每次保存已经走过的路径
  • 如果到达根节点则判断是否符合,如果不符合则回溯过去,如果符合则将答案存取起来
  • 每次调用递归后,需要将状态恢复
class Solution {
   
public:
    vector<vector<int>> result;
    bool is_leaf(TreeNode* root)
    {
   
        return (root->left==NULL&&root->right==NULL);
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) 
    {
   
        if(root==NULL) return result;
        vector<int> road;
        backtrack(root,sum,road);
        return result;    
    }
    void backtrack(TreeNode* node,int sum,vector<int
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值