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

leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code) leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code) BFS和DFS的经典应用就是在树和图中的遍历。 地图的搜索问题通常都可以用BFS和DFS解决,下面题目非常典型,并且很多题目类似,自己如果能够独立完成基本就掌握了BFS和DFS以及地图的遍历问题。 文章目录leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code)[200. 岛屿数量](https://leetcode-cn.com/problems/number-of-islands/)[127. 单词接龙](https: 阅读详情

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 = 22,
		  5
         / \
        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 sum−val,
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 = 22,

              5
             / \
            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> &road) //用引用可以降低内存
    {
        if(is_leaf(node)&&sum==node->val)  //如果是叶结点并且符合要求,则将其加入
        {       road.push_back(node->val);
                result.push_back(road);
                road.pop_back();
                return ;
        }
        if(node->left!=NULL)
        {
            road.push_back(node->val);  
            backtrack(node->left,sum-node->val,road);  //向下延申
            road.pop_back();              //恢复状态
        }
        if(node->right!=NULL)
        {
            road.push_back(node->val);
            backtrack(node->right,sum-node->val,road);//向下延申
            road.pop_back();//恢复状态
        }
    }
};
236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉树中。

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

在这里插入图片描述

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

分析:

方法一:递归法

  • 首先确定一下两个节点的情况,可能其中一个就是根节点,可能都位于根的左子树,也可能都位于根的右子树,也可能一个位于左子树,一个位于右子树
  • 如果其中一个是根节点,则最近公共祖先就是根节点
  • 如果两个都位于根的左子树,则递归调用左子树即可
  • 如果两个都位于根的右子树,则递归调用右子树即可
  • 如果一个位于左子树,一个位于右子树,则最近公共祖先一定是根节点
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
	{
    	if(root==NULL) return NULL;    
    	if(root==q||root==p) return root;//如果其中一个是root,则最近公共祖先一定是root
		
		TreeNode* left=lowestCommonAncestor(root->left,p,q);
		TreeNode* right=lowestCommonAncestor(root->right,p,q);
		if(left==NULL) //说明两个节点都在右侧
			return right;
		else if(right==NULL)//说明两个节点都在左侧 
			return left;
		else  //这里表示两个都非空 ,因为两个都存在,所以不会是全空
			return root;  //说明一个在左子树,一个在右子树,因此返回root即可 
	}
};

方法二:回溯法

思路来源:如果树存储有父结点的话,实际上会很方便地把祖先节点全部遍历,然后就比较容易找到两个树的最近公共祖先,但是题目所给的树没有父节点,因此需要从root才可以得到一个节点的祖先路径。如果我们知道从root到p的路径,也知道从root到q的路径,则很容易便可以知道最近公共祖先。即两个路径的最后一个重复的节点(可以倒序遍历,第一个相同即是)

因此采用回溯法,分别找到从root到p路径和从root到q路径即可。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
	{
    	vector<TreeNode*> path1;
    	vector<TreeNode*> path2;
    	vector<TreeNode*> p_par;
		vector<TreeNode*> q_par;
		bool finish_p=false,finish_q=false; 
		backtrack(root,p,path1,p_par,finish_p); //将p_par修改为root到p的路径
		backtrack(root,q,path2,q_par,finish_q); //将q_par修改为root到q的路径
    	for(int i=min(p_par.size(),q_par.size())-1;i>=0;i--)//找两个序列的最后一个的公共
    	{
    		if(p_par[i]==q_par[i])
    		return p_par[i];
		}
        return root;
	}
    //注意这里的几个vector参数都是引用
	void backtrack(TreeNode* node, TreeNode* p,vector<TreeNode*> &path,vector<TreeNode*> &result,bool &finish)  //finish表示是否找到,用于剪枝
	{
		if(node==NULL||finish)
		  return ;
		path.push_back(node); 
		if(node==p)
		{
			finish=true;  //找到的话就将结果保存在路径中,然后finish改为true
			result=path;
			return;
		}
		backtrack(node->left,p,path,result,finish);  //左寻 
		backtrack(node->right,p,path,result,finish);//右寻 
		path.pop_back(); //恢复状态 
	}
};
114. 二叉树展开为链表

给定一个二叉树,原地将它展开为链表。

例如,给定二叉树
    1
   / \
  2   5
 / \   \
3   4   6
将其展开为:
1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

分析:

方法一:很显然,可以看出来形成的链表是一个preorder序列,因此可以采用 O ( n ) O(n) O(n)的空间复杂度,将前序遍历的顺序存入到一个vector数组中,然后按照要求使用右指针将其串联起来即可。(就是一个用空间换取时间的策略)

class Solution {
public:
	vector<TreeNode*> pre;
    void flatten(TreeNode* root) 
	{
        preoder(root);
        pre.push_back(NULL);
        for(int i=0;i<pre.size()-1;i++)  //将链表串联起来
        {
            pre[i]->left=NULL;
        	pre[i]->right=pre[i+1];
		}
    }
    void preoder(TreeNode* root)  //前序遍历,将结果存到pre中
    {
    	if(root==NULL) return;
    	pre.push_back(root);
    	preoder(root->left);
    	preoder(root->right);
	}
};

方法二:递归

每一步的过程,实际上就是 将根节点,指向 左子树的展开,然后将左子树的展开的尾节点,指向右子树的展开

递归最大的特点在于:我们只处理当前的情况,不用去管子问题是如何解决的,只需要想着子问题已经解决了,如何将该问题解决即可。

例如,例子:

    1
   / \
  2   5
 / \   \
3   4   6
\\将问题拆解

   1
 
  	    2
   		 \
          3
           \
            4
       
                  5
                   \
                    6

代码:

class Solution {
public:
    void flatten(TreeNode* root) 
	{
        if(root==NULL) return;
        flatten(root->left);
        flatten(root->right);
        if(root->left==NULL)
			return;
		TreeNode*le=root->left;
		while(le->right!=NULL)  //找到左子树的最右边的节点,也就是展开后的尾结点 
        {
        	le=le->right;
		}
		le->right=root->right; //将左子树展开后的尾部指向右子树的头部
		root->right=root->left; //将左子树移到右边
        root->left=NULL; //左指针赋为空
    }
};

方法三:非递归

分析该树的展开,实际上每一次我们是先遍历根节点,然后先序遍历左子树,然后先序遍历右子树。因此,如果我们每一步,将右子树放置在左子树最右的节点(也就是将左子树展开后最后的节点),将不影响顺序。根据此,可以用循环的方式解决该方法。

class Solution {
public:
    void flatten(TreeNode* root) 
	{
        while (root != NULL) 
		{
            if (root->left != NULL) 
			{
                TreeNode* most_right = root->left; //左子树的最右节点 
                while (most_right->right != nullptr) 
					most_right = most_right->right; // 找最右节点
                most_right->right = root->right; // 将当前root的右子树放置在左子树最右节点的子节点处
				 
                root->right = root->left; //将root->right指向left即可 
                root->left = NULL; //置空左儿子 
            }
            root = root->right; // 继续下一个节点
        }
        return;
    }
};
102. 二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层次遍历结果: [[3],[9,20],[15,7] ]

分析:二叉树的层序遍历,也就是宽度优先搜索BFS遍历。如果将结果以一个数组的形式存储的话将变得容易很多,以层次存储,就需要考虑当前节点是第几层,因为需要将同层的放置在一起,解决这个问题可以用将添加节点和添加队列元素分开的方法。

class Solution {
public:
    vector<vector<int> > levelOrder(TreeNode* root) 
	{
        vector<vector<int> > result;//存储结果
		queue<TreeNode*> Q; //BFS的队列
		if(root==NULL) return result;
		Q.push(root);
		while(!Q.empty())
		{
			 vector<int> f; //存储这一层的答案
			 int size=Q.size(); //每一次添加前,记录size,这样只将队列的前size个val存储,等价于记录了树的深度,使同深度的节点一起
			 for(int i=0;i<size;i++)  //遍历size个节点,也就是将这一层遍历结束就停止 
			 {
			 	TreeNode* tem=Q.front();
			 	f.push_back(tem->val);
				if(tem->left!=NULL) Q.push(tem->left);
				if(tem->right!=NULL) Q.push(tem->right); 	
				Q.pop();
			 }
			 result.push_back(f);	//将当前结果存储
		} 
        return result;
    }
};
144. 二叉树的前序遍历

给定一个二叉树,返回它的 前序 遍历。

示例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]

分析:二叉树的前序遍历中序遍历后序遍历都有递归与非递归方式,通常来说,递归方式是非常简洁且容易写的,但非递归方式还是要掌握比较好。

前序遍历的递归方式:

  • 遍历二叉树的根节点
  • 如果左子树非空,则先序遍历左子树
  • 如果右子树非空,则先序遍历右子树
class Solution {
public:
    vector<int> result;
    vector<int> preorderTraversal(TreeNode* root) 
    {
        if(root==NULL) return result;  //如果是空,则返回
        result.push_back(root->val);  //将根节点的值加入
        preorderTraversal(root->left); //先序遍历左子树
        preorderTraversal(root->right); //先序遍历右子树
        return result;
    }
};

非递归方式:

可以借助一个辅助栈,先序遍历是先访问根节点,然后访问左子树,然后访问右子树。借助栈,首先将根节点入栈,与BFS遍历二叉树的层次类似,然后将右节点入栈,然后入栈左节点,将当前元素pop。每次取栈顶元素重复操作。

  1. 首先将根节点入栈
  2. 将栈顶元素取出后弹出,将该节点对应的值存储起来,如果该元素的右子树非空,则将右子树放入栈,如果该元素的左子树非空,则将左子树入栈
  3. 重复步骤2,直至栈为空
class Solution {
public:
    vector<int> result;
    vector<int> preorderTraversal(TreeNode* root) 
    {
        stack<TreeNode*> st;//辅助栈
        if(root==NULL) return result;
        st.push(root);//将根节点放入栈顶
        while(!st.empty())
        {
            TreeNode* temp=st.top();  //取栈顶后将其pop
            st.pop();
            result.push_back(temp->val);     
            if(temp->right!=NULL) st.push(temp->right);//先存右子树,再存左子树
            if(temp->left!=NULL) st.push(temp->left);
        }
        return result;
    }
};
199. 二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例:

输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

分析:右视图,也就是每一层的最右边的元素,因此可以考虑在层次遍历的基础上,记录每一层的最后一个元素即可,因此,掌握层序遍历的话搞定该题应该是较为容易的。

如果在每次遍历一层后重新读取size,就可以等价于更新了新的层数,否则的话就需要存储层数,那样的话可以考虑用paire的方式将每个节点与层数联系起来。

class Solution {
public:
    vector<int> rightSideView(TreeNode* root)
	{
        vector<int> result;//存储结果
		queue<TreeNode*> Q; //BFS的队列
        TreeNode* tem;
		if(root==NULL) return result;
		Q.push(root);
		while(!Q.empty())
		{
	   int size=Q.size(); //每一次添加前,记录size,这样只将队列的前size个val存储,等价于记录了树的深度,使同深度的节点一起
			 for(int i=0;i<size-1;i++)  //遍历前size-1个节点时只将其左右子树存储即可 
			 {
			 	tem=Q.front();
				if(tem->left!=NULL) Q.push(tem->left);
				if(tem->right!=NULL) Q.push(tem->right); 	
				Q.pop();
			 }
             tem=Q.front(); //此时的front就是一层的最后一个节点
             result.push_back(tem->val);
             if(tem->left!=NULL) Q.push(tem->left);
			 if(tem->right!=NULL) Q.push(tem->right); 	
			 Q.pop();     
        } 
        return result;
    }
};
105. 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:
    3
   / \
  9  20
    /  \
   15   7

分析:重构二叉树的条件是已知中序序列以及前序序列和后序序列的其中一个。

该题中,已知前序序列和中序序列。

首先考虑这两种序列的遍历形式:

前序序列:先遍历根节点,然后左子树,然后右子树

中序序列:先遍历左子树,然后根节点,然后右子树

因此,我们已知前序序列,则前序序列的第一个元素是根节点内容。然后根据该节点的值,在中序序列中找到该值的位置,则可以根据中序序列确定出左子树和右子树的元素集合。根据由中序序列得到的左子树和右子树的中序遍历,可以在前序序列中找到左子树和右子树的前序遍历序列。因此,很容易考虑递归即可。

(该代码由于每次将新的子树序列进行生成,因此空间和时间上都不优秀,可以再写一个函数,不去生成新的子列,只标记一下每个子列的起始和结束位置即可)。

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        if(preorder.size()==0)
			return NULL;
		TreeNode *root = new TreeNode(preorder[0]);
		vector<int> pre_before;
		vector<int> pre_after;
		vector<int> vin_before;
		vector<int> vin_after;
		int st=0;
		while(preorder[0]!=inorder[st])
		{
			st++;
		} //st表示中序遍历根的位置
		for(int i=0;i<st;i++)
		{
			vin_before.push_back(inorder[i]);
		}
		for(int i=st+1;i<inorder.size();i++)
		{
			vin_after.push_back(inorder[i]);
		}
		for(int i=1;i<=vin_before.size();i++)
		{
			pre_before.push_back(preorder[i]);
		}
		for(int i=pre_before.size()+1;i<preorder.size();i++)
		{
			pre_after.push_back(preorder[i]);
		} 
		root->left=buildTree(pre_before,vin_before);
		root->right=buildTree(pre_after,vin_after);
		return root;
    }
};
101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
    1
   / \
  2   2
   \   \
   3    3

分析:一个树何时是镜像对称的,即一个树的左右两个子树是镜像对称的。

因此,如何才能判断两个数是镜像对称的?

使用递归:

  • 如果两个树都是空,说明是镜像对称的
  • 如果两个树根节点的值相同且一个树的左子树与另一个树的右子树镜像对称,一个树的右子树和另一个树的左子树镜像对称,则两个树是镜像对称的
  • 以上如有一个不成立,则不对称
class Solution {
public:
    bool isSymmetric(TreeNode* root) 
    {
        if(root==NULL) return true;
        return isSymmetric(root->left,root->right);    
    }
    bool isSymmetric(TreeNode* node1,TreeNode* node2)
    {
        if(node1==NULL&&node2==NULL) return true;
        if(!(node1!=NULL&&node2!=NULL)) return false; //两个其中一个是NULL
        return (node1->val==node2->val)&&isSymmetric(node1->left,node2->right)&&isSymmetric(node1->right,node2->left);
    }
};
104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

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

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

分析:很显然递归可以较好的解决该问题,如果根节点不为空,则二叉树的最大深度等于 1+max(左子树最大深度,右子树最大深度)

class Solution {
public:
    int maxDepth(TreeNode* root) 
    {
        if(root==NULL) return 0;
        return 1+max(maxDepth(root->left),maxDepth(root->right));        
    }
};

由于每个节点都遍历一遍,因此时间复杂度为 O ( n ) O(n) O(n), 空间复杂度为 O ( l o g n ) O(logn) O(logn) ,最坏情况下树为直线,则空间复杂度将为 O ( n ) O(n) O(n)

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

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

示例:

给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最小深度  2

分析:和上题类似,但是这里需要注意最小深度是到最近的叶子节点,因此如果左子树为空,应该为1+右子树的最小深度,如果右子树为空,应该为1+左子树的最小深度。否则应该是1+min(左子树最小深度,右子树最小深度)

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==NULL) return 0;
        if(root->left==NULL)
            return 1+minDepth(root->right);
        if(root->right==NULL)
            return 1+minDepth(root->left);
        return 1+min(minDepth(root->left),minDepth(root->right));      
    }
};
leetcode二叉搜索树经典题目(思路、方法、code) 文章目录二叉搜索树的简介[98. 验证二叉搜索树](https://leetcode-cn.com/problems/validate-binary-search-tree/)[700. 二叉搜索树中的搜索](https://leetcode-cn.com/problems/search-in-a-binary-search-tree/)[701. 二叉搜索树中的插入操作](https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/) 阅读详情

相关推荐

LeetCode面试经典150题:高效算法刷题指南

算法与数据结构是技术面试的核心考察点,掌握常见题型和解题思路对求职至关重要。LeetCode经典150题精选了面试中最常出现的算法问题,覆盖数组、链表、树、动态规划等关键数据结构。通过系统化的刷题方法,如五步刷题法和错题本策略,可以有效提升解题能力。动态规划和二叉树等高频题型需要特别关注,理解其底层原理和应用场景。本文结合工程实践,分享如何高效准备算法面试,包括刷题计划制定、面试解题步骤和常见问题应对策略,帮助开发者在有限时间内最大化提升算法能力。

weixin_34168880的博客 361

二叉树常见解题方法

文章目录一、利用递归遍历框架解题题目1:二叉树的深度(leetcode)题目2:二叉树的直径(leetcode)1、特殊场景-两个节点同时遍历题目3:对称二叉树(leetcode)题目4:填充每个节点的下一右侧节点指针(leetcode)2、特殊场景-构建二叉树二、利用层次遍历解题题目6:二叉树的层序遍历(leetcode)题目7: 填充每个节点的下一个右侧节点指针(leetcode) 一、利用递归遍历框架解题 二叉树解题重点在于利用思考根节点、左子树、右子数的关系,其余工作交给遍历处理,二叉树递归基本框架

u012866052的博客 2449

LeetCode 面试经典 150 题回顾

最经典 150 题,掌握面试所有知识点 面试经典 150 题 : 题目分析、解题思路、复杂度分析、代码展示

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 8万+

二叉树的题目练习总集(一次做到爽)

摘要:建立二叉树、前中后层序、求树高度、叶子结点个数、k层结点个数、结点是否存在于二叉树、两个叶子最近公共祖先、判断平衡树、求二叉树最远两个结点距离。 目录 分析需求: 一、节点 二、队列 三、树 1、树的基本方法:建立二叉树。 2、求前中后层遍历 3、求树的高度: 4、求叶子节点个数 5、求二叉树第k层的结点个数 6、判断一个结点是否在二叉树中? 7、求两个结点的...

雀黑够呛哥 3203

计算机数据结构二叉树测试题

,包含数据结构中二叉树的许多试题包

计算机二级二叉树试题专题

计算机二级二叉树专题 主要介绍有关二叉树的知识点和二叉树题型的解法

LeetCode刷题------二叉树

跟着代码随想录学二叉树

weixin_43526403的博客 426

步科触摸屏编程

1.首先官网上下载kinco软件,然后再安装驱动,安装的方式是需要两个文件。把两个文件放到driver文件夹下面,然后设备管理器右键更新,手选driver文件夹,自动安装即可。 步科触摸屏驱动文件下载地址 2.按照步科触摸屏使用手册一步一步来建立工程 Kinco HMIware使用手册下载地址 登录界面 涉及到的是页面切换,用的是login window,然后只留下等级输入那个

MAYBE的博客 2万+

1.二叉树的解题思路(基础篇)

算法学习的积累旅程~

wang19970515的博客 193

MPC模型预测控制实战:从理论到代码实现(Python示例)

本文详细介绍了MPC模型预测控制的实战应用,从理论到Python代码实现。通过构建系统模型、预测方程、优化问题及约束处理,展示了如何实现一个完整的MPC控制器。文章还提供了水箱液位控制的应用案例,帮助读者掌握MPC在工业控制中的实际应用。

weixin_42653691的博客 461

OpenWRT端口转发与NAT环回冲突的排查与解决

本文详细解析了OpenWRT路由器中端口转发与NAT环回功能冲突导致的内网访问故障。通过生活化类比阐明两者工作原理,提供从基础诊断到内核参数调整、LuCI选项配置及手动编写iptables规则的多套解决方案,并给出进阶排查思路,帮助用户彻底解决内网无法通过公网地址访问服务的常见问题。

weixin_29243279的博客 507

计算机二级:树与二叉树速记公式及特殊例题

简单整理计算机二级树与二叉树相关公式概念,无废话,有错误请指出我没太费心思,公式、例题均来自网络及视频。

FBJSSSSS的博客 1万+

【干货】S7-PLCSIM Advanced V3.0 无法启动实例( Error Code:-30,LicenseNotFound)问题解决方法

【干货】S7-PLCSIM Adavanced V3.0 无法启动实例( Error Code:-30,LicenseNotFound)问题解决方法

handinvv的博客 5万+

LeetCode 力扣算法题解汇总,All in One

我刷过的所有 leetcode 算法题解的汇总。 题目的排列顺序是按照先Easy再Medium再Hard排列的,暂时还没有把题目全部整理完成。后序我会把刷过的所有的题目都整理到这个文档里。 如果想看我全部的力扣算法题解,可以看我的题解博客:[fuxuemingzhu.cn](fuxuemingzhu.cn)

负雪明烛 1万+

YOLO26改进策略【卷积层】| HWD,引入`Haar小波变换`到下采样模块中,减少信息丢失

本文记录的是。传统的卷积神经网络中常用的最大池化平均池化和步长为2的卷积等操作进行下采样可能会导致信息丢失,为了解决信息丢失问题,HWD作者受无损信息变换方法的启发,引入Haar小波变换到下采样模块中,

Limiiiing的博客 348

编织数据的实时脉络——构建基于MySQL的数据编织平台,实现实时数据治理

除了上述基本设置外,我们还可以根据实际应用场景自定义一些特定的监控项目。例如,对于某些高并发读写的表,可能需要特别关注它们的锁等待时间和回滚段使用率;而对于涉及到跨库关联查询的操作,则应当着重检查网络延迟及缓存命中率等因素。-- 获取InnoDB行级锁等待情况-- 统计各表的缓存命中率这段SQL脚本不仅展示了如何查询InnoDB引擎下的锁争用状况,还介绍了计算表级别缓存命中率的方法,有助于深入理解系统的运行状态。

墨夶的博客 1789

【GitHub项目推荐--LeetCodeAnimation:用动画的形式呈现LeetCode题目思路】

​​ 是一个创新的开源项目,由MisterBooo(吴师兄)创建,致力于用动画的形式演示LeetCode题目的解题思路。该项目通过直观的动画可视化,帮助开发者更好地理解和掌握算法和数据结构的核心概念,让抽象的算法变得生动易懂。🔗 ​GitHub地址🚀 ​核心价值​:动画演示 · 算法可视化 · 学习辅助 · 直观理解​项目背景​:​学习痛点​:解决算法学习抽象难懂的问题​视觉学习​:利用动画提升学习效果和理解深度​创新教学​:创新的算法教学方法​长期规划​:3-4年完成所有题目动画化​。

j8267643的博客 1060

《Zephyr OS 入门与实战》第3章:第一个 Zephyr 程序 - Blinky 实战

解决方法:确认设备树overlay文件已正确加载。返回值,确认驱动初始化状态。

2301_79143213的博客 541

10 道经典的 LeetCode 题目,结合 C++ 语言的实现,每道题目都包含详细的分析过程、代码实现和示例输出

以下是 10 道经典的 LeetCode 题目,结合 C++ 语言的实现,每道题目都包含详细的分析过程、代码实现和示例输出。

分享平时的学习心得和笔记 1097

【Dumper-7】入门指南 - 带你领略不一样的UE世界

摘要: Dumper-7是一款用于分析UE4/UE5游戏的逆向工具,可自动生成游戏内部结构的C++ SDK。支持Visual Studio、CMake和Xmake三种构建方式,通过DLL注入目标游戏后,自动识别引擎结构并输出C++ SDK文件(默认保存在C:\Dumper-7目录)。该工具适用于游戏Mod开发、安全研究和机制分析,提供完整的类层次映射、属性/函数识别功能。使用时需注意x64平台配置,生成SDK后可集成到自定义DLL项目中,通过示例代码展示如何查找游戏对象、访问世界状态和调用引擎函数。

kinghzking的专栏 437

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

二叉树所有路径求解(力扣257)

以上就是针对这道题的刷题笔记,讲解了怎么用递归以及回溯求解二叉树的所有路径问题,用前序遍历遇到叶子结点时则回溯到上面去重新遍历,还用到了stringbuilder来拼接字符串。

Huahua_1223的博客 1396

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【算法比赛】2020 力扣杯!Code Your Future 春季全国编程大赛

这个比赛,除了最后一题,其他四题其实没啥难度。 第一题:字符串操作。 第二题:模拟。 第三题:分析。 第四题:DP。 详细题解如下。 1.重新格式化字符串(Reformat the String) AC代码(C++) 2.点菜展示表(Display Table of Food Orders in A Restaurant) AC代码(C+...

Mikchy的博客 2063

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

如何优雅地刷力扣 LeetCode - Easy

App > LeetCode > 题库 > 题解。

媛媛 854

【leetcode刷题】26.翻转二叉树——Java版

欢迎订阅《leetcode》专栏

公号:一条coding 1万+

leetcode 二叉树进阶题目

二叉树进阶题目

apigthatcanfly的博客 269

力扣257. 二叉树的所有路径(遍历思想解决)

力扣257. 二叉树的所有路径(遍历思想解决)

LNsupermali的博客 940
上一篇: 归并排序和逆序数(思路、code)
下一篇: leetcode二叉搜索树经典题目(思路、方法、code)
coding丁
博客等级 码龄9年 383粉丝 147原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值