leetcode--二叉树

144. 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历

思路:
对于前序,中序,后序,这里我们可以采用两种办法,一种是递归方法,这个方法对于这三种代码最简洁且变化不大。另一种方法是迭代的方法,这个方法对于这三种遍历,变化较大需要进行区分。

递归法:

struct TreeNode{
	int val;
	Treenode *left;
	TreeNode *right;
	TreeNode(int x):val(x),left(NULL),right(NULL){}
};
class Solution{
public:
void Traveral(TreeNode *cur, vector<int> vec){
	if(cur==NULL) return;
	vec.push_back(cur->val);
	Traversal(cur->left,vec);
	Traversal(cur->right,vec);
}
vector<int> PreorderTraversal(Treenode *root){
	vector<int> result;
	Traversal(root,result);
	return result;
}
};

迭代法:

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x),right(NULL),left(NULL){}
};
class Solution{
public:
	vecot<int> preordertraversal(TreeNode *root){
		stack<TreeNode*>st;
		vector<int> result;
		if(root==NULL) return result;
		st.push(root);
		while(!st.empty()){
			TreeNode *node=st.top();
			result.push_back(node->val);
			st.pop();
			if(node->right) st.push(node->right);
			if(node->left) st.push(node->left);
		}
		return result;
	}
};

中序遍历
左中右
递归法,和前序差别不大,只是在遍历的时候改一下顺序即可,这里着重介绍迭代法

class Solution{
	public:
		vector<int> inorderTraversal(TreeNode *root){
			stack<TreeNode*> st;
			TreeNode *node=root;
			vector<int> result;
			while(node!=NULL || !st.empty()){
				if(node!=NULL){
					st.push(node);
					node=node->left;
				}else{
					node=st.top();
				 	st.pop();
					result.push_back(node->val);
					node=node->right;
				}
			}
			return result;
		}
};

145. 二叉树的后序遍历

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

示例:

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

   1
    \
     2
    /
   3 

输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?

思路:
递归,迭代
1.递归

class Solution{
	public:
		void traversal(TreeNode *node,vector<int>&result){
			if(node==NULL)return;
			traversal(node->left,result);
			traversal(node->right,result);
			result.push_back(node->val);
		}
		vector<int> postorderTraversal(TreeNode* root) {
			vector<int> result;
			traversal(root,result);
			return result;
		}
};

迭代:

class Solution{
	public:
		vector<int> postorderTraversal(TreeNode* root){
			vector<int> result;
			stack<TreeNode*> st;
			if(root==NULL) return result;
			st.push(root);
			while(!st.empty()){
				TreeNode *node=st.top();
				st.pop();
				result.push_back(node->val);
				if(node->left) st.push(node->left);
				if(node->right) st.push(node->right);
			}
			reverse(result.begin(),result.end());
			return result;
		}
};

统一的迭代法写前中后序

上面的额迭代法,对于中序来说,和前序和后序的写法不同,所以这里推荐一个统一的写法,我们考虑的时候对于要处理的元素进行标记即可。

class Solution{
	public:
		vector<int> inordertraversal(TreeNode *root){
			vector<int> result;
			stack<TreeNode*> st;
			if(root!=NULL) return st.push(root);
			while(!st.empty()){
				TreeNode *node=st.top();
				if(node!=NULL){
					st.pop();
					if(node->right) st.push(node->right);  //右
					st.push(node);  //中
					st.push(NULL);  //中
					if(node->left) st.push(node->left);  //左
				}else{
					st.pop();
					node=st.top();
					st.pop();
					result.push_back(node->val);
				}
			}
			return result;
		}
};

前序,后续只是位置不同而已

102. 二叉树的层序遍历

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

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

    3
   / \
  9  20
    /  \
   15   7

返回其层序遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

思路:
这里要使用队列方式,进行遍历

class Solution{
	public:
		vector<vector<int>> levelorder(TreeNode *root){
			queue<TreeNode*> que;
			vector<vector<int>> result;
			if(root!=NULL) que.push(root);
			while(!que.empty()){
				int size=que.size();
				vector<int> vec;
				for(int i=0;i<size;i++){
					TreeNode *node=que.front();
					que.pop();
					vec.push_back(node->val);
					if(node->left) que.push(node->left);
					if(node->right) que.push(node->right);
				}
				result.push_back(vec);
			}
			return result;
		}
};

226. 翻转二叉树

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

思路:
对于镜像二叉树,有两种方法,一中是按照原来前序,中序,后续遍历的时候到每个节点进行左右子树交换。
另一种是使用递归的方法

方法1,递归

class Solution{
	public:
		TreeNode* inverttree(TreeNode *root){
			if(root==NULL) return root;
			swap(root->left,root->right);
			inverttree(root->left);
			inverttree(root->right);
			return root;
		}
};

方法2:迭代法

class Solution{
	public:
		TreeNode *inverttree(TreeNode *root){
			stack<TreeNode*>st;
			if(root!=NULL)  st.push(root);
			while(!st.empty()){
				TreeNode *node=st.top();
				if(node!=NULL){
					st.pop();
					if(node->right) st.push(node->right);
					if(node->left) st.push(node->left);
					st.push(node);
					st.push(NULL);
				}else{
					st.pop();
					node=st.top();
					st.pop();
					swap(node->left,node->right);
				}
			}
			return root;
		}
};

N叉树的前序遍历

思路:
因为N叉树的子树不一定是两个,但是我们遍历的时候还是按照前序的规则进行只是代码中需要进行修改

//首先在节点的定义上和二叉树的TreeNode的结构体的定义是不同的
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};

class Solution{
	void traversal(Node *node, vector<int> &result){
		if(node==NULL) return;
		result.emplace_back(node->val);
		int size=node->children.size();
		for(int i=0;i<size;i++){
			Node *n=node->children[i];
			if(n!=NULL){
				traversal(n,result);
			}
		}
	}
	vector<int> Preorder(Node *root){
		vector<int> result;
		if(root==NULL) return result;
		traversal(root,result);
		return result;
	}
};

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

迭代法:

class Solution{
	public:
		bool isSymmetric(TreeNode *root){
			if(root==NULL) return true;
			queue<TreeNode*> que;
			que.push(root->left);
			que.push(root->right);
			while(!que.empty()){
				TreeNode *leftnode=que.front();
				que.pop();
				TreeNode *rightnode=que.front();
				que.pop();
				if(!leftnode && !rightnode){
					continue;
				}
				if(!leftnode || !rightnode || leftnode->val != rightnode->val){
					return false;
				}
				que.push(leftnode->left);
				que.push(rightnode->right);
				que.push(leftnode->right);
				que.push(rightnode->left);
			}
			return true;
		}
};

104. 二叉树的最大深度

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

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

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

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

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

递归

class Solution{
	public:
		int getDepth(TreeNode *node){
			if(node==NULL) return 0;
			int leftdepth=getDepth(node->left);
			int rightdepth=getDepth(node->right);
			return leftdepth>rightdepth?leftdepth+1:rightdepth+1;
		}
		int maxDepth(TreeNode *root){
			return getDepth(root);	
		}
};

迭代:

class Solution{
	public:
		int maxDepth(TreeNode *root){
			queue<TreeNode*> que;
			int depth=0;
			if(root!=NULL) que.push(root);
			while(!que.empty()){
				int size=que.size();
				depth++;
				for(int i=0;i<size;i++){
					TreeNode *node=que.front();
					que.pop();
					if(node->left) que.push(node->left);
					if(node->right) que.push(node->right);
				}
			}
			return depth;
		}
};

559. N 叉树的最大深度

给定一个 N 叉树,找到其最大深度。

最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。

class Solution{
	public:
	int maxDepth(Node *root){
		int depth=0;
		queue<Node*> que;
		if(root==NULL) return 0;
		if(root!=NULL) que.push(root);
		while(!que.empty()){
			depth++;
			int size=que.size();
			for(int i=0;i<size;i++){
				Node *node=que.front();
				que.pop();
				for(int j=0;j<node->children.size();j++){
					if(node->children[j]) que.push(node->children[j]);
				}
			}
		}
		return depth;
	}
};

111. 二叉树的最小深度

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

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

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

输入:root = [3,9,20,null,null,15,7]
输出:2
示例 2:

输入:root = [2,null,3,null,4,null,5,null,6]
输出:5

递归法:

  1. 确定参数和返回值
    int minDepth(TreeNode *root)
  2. 确定终止条件
    if(node==NULL) return 0;
    遇到空节点返回0
  3. 单层递归逻辑
    if(root->left!=NULL && root->rightNULL) return 1+leftdepth;
    if(root->left
    NULL && root->right!=NULL) return 1+rightdepth;
    if(root->left!=NULL && root->right!=NULL) depth=min(leftdepth,rightdepth);

注意这里我们和求最大深度不同,因为最大深度就是距离根节点最远的叶子节点的深度,但是我们求最小深度的话是求最近叶子节点的距离,如果按照之前求最大的逻辑,如果一个根节点没有左子树或右子树这样最小深度就是1,但是并不是这样。

class Solution{
	public:
		int minDepth(TreeNode *root){
			if(root==NULL) return 0;
			int depth=0;
			int leftdepth=minDepth(root->left);
			int rightdepth=minDepth(root->right);
			if(root->left!=NULL && root->right==NULL) return 1+leftdepth;
			if(root->left==NULL && root->right!=NULL) return 1+rightdepth;
			if(root->left!=NULL && root->right!=NULL)  depth=min(leftdepth,rightdepth);
			return depth+1;
		}
};

迭代法:
和二叉树求最大深度的迭代法类似,只不过多做了一次判断如果左右子树都为空的时候,就要返回深度。

class Solution{
	public:	
		int minDepth(TreeNode *root){
			if(root==NULL) return 0;
			int depth=0;
			queue<TreeNode*> que;
			if(root!=NULL)  que.push(root);
			while(!que.empty()){
				depth++;
				int size=que.size();
				for(int i=0;i<size;i++){
					TreeNode *node=que.front();
					que.pop();
					if(node->left) que.push(node->left);
					if(node->right) que.push(node->right);
					if(!node->left &&!node->right) return depth;
				}
			}
			return depth;
		}
};

222. 完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

输入:root = [1,2,3,4,5,6]
输出:6
示例 2:

输入:root = []
输出:0
示例 3:

输入:root = [1]
输出:1

思路:
使用层次序遍历,然后每到一个节点+1即可

class Solution {
public:
    int countNodes(TreeNode* root) {
        int count=0;
        if(root==NULL) return 0;
        queue<TreeNode*>que;
        if(root!=NULL) que.push(root);
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode *node=que.front();
                que.pop();
                count++;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return count;
    }
};

递归法:
就是先求左子树节点数量,再求右子树节点数量,最后求和+1即可,为什么要加1,因为还要加上根节点

class Solution{
	public:
		int countNodes(TreeNode* root) {
        int count=0;
        if(root==NULL) return 0;
        int leftnodenum=countNodes(root->left);
        int rightnodenum=countNodes(root->right);
        count=leftnodenum+rightnodenum+1;
        return count;
    }
};

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

输入:root = [3,9,20,null,null,15,7]
输出:true

思路:
使用递归法:
1.确定返回值和参数
int getDepth(TreeNode *node){}
这个函数中,看高度差的绝对值,如果左子树和右子树差的绝对值大于1说明就不是平衡二叉树
2.终止条件
if(node==NULL) return -1;
3.单层递归逻辑
int leftdepth=getDepth(node->left);
int rightdepth=getDepth(node->right);
return abs(leftdepth-rightdepth)>1?-1:1+max(leftdepth, rightdepth);

class Solution{
	public:
		int getDepth(TreeNode* node){
			if(node==NULL) return 1;
			int leftdepth=getDepth(node->left);
			if(leftdepth==1) return -1;
			int rightdepth=getDepth(node->right);
			if(rightdepth==-1) return -1;
			return abs(leftdepth-right)>1?-1:1+max(leftdepth,rightdepth);
		}
		    bool isBalanced(TreeNode* root) {
        		return getDepth(root)==-1?false:true;
    }
};

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。

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

示例:

输入:

   1
 /   \
2     3
 \
  5

输出: ["1->2->5", "1->3"]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

思路:
求路径按照前序遍历的方法,遇到叶子节点说明这是一条路径,然后要进行回溯,每一次递归就必然又一次回溯

class Solution{
	public:
		void traversal(TreeNode* node, vector<int> &path, vector<string> &result){
			path.push_back(node->val);
			if(node->left==NULL && node->right==NULL){
				string spath;
				for(int i=0;i<path.size()-1;i++){
					spath+=to_string(path[i]);
					spath+="->";
				}
				spath+=to_string(path[path.size()-1]);
				result.push_back(path);
			}
			if(node->left){
				traversal(node->left, path, result);
				path.pop_back();
			}
			if(node->right){
				traversal(node->right,path,result);
				path.pop_back();
			}
		}
		vector<string> binaryTreePaths(TreeNode* root) {
			vector<int> path;
			vector<string> result;
			if(root==NULL) return result;
			traversal(root,path,result);
			return result;
		}
};

404. 左叶子之和

计算给定二叉树的所有左叶子之和。

示例:

    3
   / \
  9  20
    /  \
   15   7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

思路:
递归
1.参数和返回值
int sumOfLeftLeaves(TreeNode* root){}
2.终止条件
if(node==NULL) return 0;
3.递归逻辑

int leftnum=sumOfLeftLeaves(node->left);
int rightnum=sumOfLeftLeaves(node->right);
if(node->left != NULL && node->left->left==NULL && node->left->right==NULL) result+=node->left->val;
int sum=leftnum+rightnum+result;

我们判断一个节点是不是左子叶节点,要根据他的父节点看是否他是左节点

class Solution{
	public:
		int sumOfLeftLeaves(TreeNode *root){
			int result=0;
			if(root==NULL) return 0;
			int leftnum=sumOfLeftLeaves(root->left);
			int rightnum=sumOfLeftLeaves(root->right);
			if(root->left!=NULL && root->left->left==NULL && root->left->right==NULL) result+=root->left->val;
			int sum=leftnum+rightnum+result;
			return sum;
		}
};

使用迭代法:前序遍历

class Solution{
	public:
		int sumOfLeftLeaves(TreeNode *root){
			if(root==NULL) return 0;
			stack<TreeNode*> st;
			int sum=0;
			st.push(root);
			while(!st.empty()){	
				TreeNode *node=st.top();
				st.pop();
				if(node->left!=NULL && node->left->left==NULL && node->left->right==NULL){
					sum+=node->left->val;
				}
				if(node->right) st.push(node->right);
				if(node->left) st.push(node->left);
			}
			return sum;
		}
}

513. 找树左下角的值

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

class Solution{
	public:
		int maxlen=INT_MIN;
		int maxleftvalue;
		void traversal(TreeNode* node, int leftlen){
			if(node->left==NULL && node->right==NULL){
				if(leftlen>maxlen){
					maxlen=leftlen;
					maxleftvalue=node->lval;
				}
				return;
			}
			if(node->left){
				leftlen++;
				traversal(node->left,leftlen);
				leftlen--;
			}
			if(node->right){
				leftlen++;
				traversal(node->right,leftlen);
				leftlen--;
			}
			return;
		}
		int findBottomLeftValue(TreeNode* root) {
        traversal(root,0);
        return maxleftvalue;
    }
};

迭代法:
使用层次序遍历

		int findBottomLeftValue(TreeNode* root) {
            queue<TreeNode*> que;
            if(root!=NULL) que.push(root);
            int result=0;
            while(!que.empty()){
                int size=que.size();
                for(int i=0;i<size;i++){
                    TreeNode *node=que.front();
                    que.pop();
                    if(i==0) result=node->val; //记录最后一行的第一个节点即可
                    if(node->left) que.push(node->left);
                    if(node->right) que.push(node->right);
                }
            }
            return result;
    }

112. 路径总和

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

叶子节点 是指没有子节点的节点。

思路:首先想到用前序遍历,求每一条路径的路径和。

class Solution{
	public:
		bool hasPathSum(TreeNode* root, int targetSum) {
			stack<pair<TreeNode*,int>> st;
			if(root!=NULL) st.push(pair<TreeNode*,int>(root,root->val));
			while(!st.empty()){
				pair<TreeNode*,int>node=st.top();
				st.pop();
				if(!node.first->right && !node.first->left && node.second==targetSum){
					return true;
				}
				if(node.first->right){
					st.push(pair<TreeNode*,int>(node.first->right, node.second+node.first->right->val));
				}
				if(node.first->left){
					st.push(pair<TreeNode*,int>(node.first->left, node.second+node.first->left->val));
				}
			}
			return false;
		}
};

递归:
递归的方法更好理解,相当于一个逆向思维,我们不需要每次对节点进行相加求和,我们做减操作,看最后到叶子节点是否为0即可

class Solution{
	public:	
		bool traversal(TreeNode* node, int count){
			if(!node->left && !node->right && count==0) {
				return true;	
			}
			if(!node->left && !node->right){
				 return false;
			}
			if(node->left){
				count-=node->left->val;
				if(traversal(node->left,count)){
					return true;
				}
				count+=node->left->val;
			}
			if(node->right){
				count-=node->right->val;
				if(traversal(node->right,count)){
					return true;
				}
				count+=node->right->val;
			}
			return false;
		}
		bool hasPathSum(TreeNode* root, int targetSum) {
			if(root==NULL) return false;
			return traversal(root,targetSum-root->val);
		}
};

113. 路径总和 II

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

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
示例 2:

输入:root = [1,2,3], targetSum = 5
输出:[]
示例 3:

输入:root = [1,2], targetSum = 0
输出:[]

思路:
递归法:
我们找到之后不需要返回值,而是把它存放到数组中。注意我们这里是遍历整个树,所以不需要返回值

class Solution{
	public:
		vector<vector<int>> result;
		vector<int> record;
		void traversal(TreeNode * node, int count){
			if(!node->left && !node->right && count==0){
				result.push_back(record);
				return;
			}
			if(!node->left && !node->right){
				return;
			}
			if(node->left){
				count-=node->left->val;
				record.push_back(node->left->val);
				traversal(node->left,count);
				count+=node->left->val;
				record.pop_back();
			}
			if(node->right){
				count-=node->right->val;
				record.push_back(node->right->val);
				traversal(node->right,count);
				count+=node->right->val;
				record.pop_back();
			}
			return;
		}
		vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
			if(root==NULL) return result;
			record.push_back(root->val);
			traversal(root,targetSum-root->val);
			return result;	
		}
};
  1. 从中序与后序遍历序列构造二叉树
    根据一棵树的中序遍历与后序遍历构造二叉树。

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

例如,给出

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

思路:
后序的最后一个数是根节点,所以我们根据这个特点将中序和后序进行划分这样就找到了二叉树

class Solution{
	public:
		TreeNode* traversal(vector<int>inorder, vector<int>postorder){
		//一般后序最后一个节点是根节点所以先要判断
			if(postorder.size()==0) return NULL;
			//得到根节点
			int rootvalue=postorder[postorder.size()-1];
			//构建二叉树
			TreeNode *root=new TreeNode(rootvalue);
			if(postorder.size()==1) return root;
			//看根节点在中序中的位置
			int delimiter;
			for(delimiter=0;delimiter<inorder.size();delimiter++){
				if(inorder[delimiter]==rootvalue) break;
			}
			//划分中序为左右两个部分
			vector<int>leftinorder(inorder.begin(),inorder.begin()+delimiter);
			vector<int>rightinorder(inorder.begin()+delimiter+1,inorder.end());
			//后序因为以及确定了根节点,所以这里需要确定新的根节点
			postorder.resize(postorder.size()-1);
			//划分后序为左右两个部分
			vector<int>leftpostorder(postorder.begin(),postorder.begin()+leftinorder.size());
			vector<int>rightpostorder(postorder.begin()+leftinorder.size(),postorder.end());
			//递归构建
			root->left=traversal(leftinorder,leftpostorder);
			root->right=traversal(rightinorder,rightpostorder);
			return root;
		}
		TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
			if(inorder.size()==0 || postorder.size()==0) return NULL;
			return traversal(inorder,postorder);
		}
};

105. 从前序与中序遍历序列构造二叉树

给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

思路:这个题和上一个题的解法类似

class Solution{
	public:
		TreeNode* traversal(vector<int>preorder, vector<int>inorder){
			if(preorder.size()==0) return NULL;
			int rootvalue=preorder[0];
			TreeNode *root=new TreeNode(rootvalue);
			if(preorder.size()==1) return root;
			int delimiter;
			for(delimiter=0;delimiter<inorder.size();delimiter++){
				if(inorder[delimiter]==rootvalue) break;
			}
			vector<int> leftinorder(inorder.begin(),inorder.begin()+delimiter);
			vector<int>rightinorder(inorder.begin()+delimiter+1,inorder.end());
			vector<int>leftpreorder(preorder.begin()+1,preorder.begin()+1+leftinorder.size());
			vector<int>rightpreorder(preorder.begin()+1+leftinorder.size(), preorder.end());
			root->left=traversal(leftpreorder,leftinorder);
			root->right=traversal(rightpreorder,rightinorder);
			return root;
		}
		TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
			if(preorder.size()==0 || inorder.size()==0) return NULL;
			return traversal(preorder,inorder);
		}
};

654. 最大二叉树

给定一个不含重复元素的整数数组 nums 。一个以此数组直接递归构建的 最大二叉树 定义如下:

二叉树的根是数组 nums 中的最大元素。
左子树是通过数组中 最大值左边部分 递归构造出的最大二叉树。
右子树是通过数组中 最大值右边部分 递归构造出的最大二叉树。
返回有给定数组 nums 构建的 最大二叉树 。

思路:
使用前序遍历的方法
我们找到这个数组中的最大值,然后记录它的位置
然后在他的左半部分继续找最大值,记录位置,有半部分同理,整个递归的逻辑

  1. 确定参数和返回值
TreeNode* constructMaximumBinaryTree(vector<int>& nums){}
  1. 确定终止条件
TreeNode *node=new TreeNode(0);
if(nums.size()==1){
	node->val=nums[0];
	return node;
}
  1. 单层递归逻辑
求最大值和位置
int maxvalue=0;
int maxvalueindex=0;
for(int i=0;i<nums.size();i++){
	if(nums[i]>maxvalue){
		maxvalue=nums[i];
		maxvalueindex=i;
	}
}
左半部分
if(maxvalueindex>0){
	vector<int>newc(nums.begin(),nums.begin()+maxvalueindex);
	node->left=constructMaximumBinaryTree(newc);
}
右半部分
if(maxvalueindex<(nums.size()-1)){
	vector<int>newc1(nums.begin()+maxvalueindex+1,nums.end());
	node->right=constructMaximumBinaryTree(newc1);
}

所有代码

TreeNode* constructMaximumBinaryTree(vector<int>& nums){
	TreeNode *node=new TreeNode(0);
	if(nums.size()==1){
		node->val=nums[0];
		return node;
	}
	int maxvalue=0;
	int maxvalueindex=0;
	for(int i=0;i<nums.size();i++){
		if(nums[i]>maxvalue){
			maxvalue=nums[i];
			maxvalueindex=i;
		}
	}
	node->val=maxvalue;
	if(maxvalueindex>0){
		vector<int>newc(nums.begin(),nums.begin()+maxvalueindex);
		node->left=constructMaximumBinaryTree(newc);
	}
	if(maxvalueindex<(nums.size()-1)){
		vector<int>newc1(nums.begin()+maxvalueindex+1,nums.end());
		node->right=constructMaximumBinaryTree(newc1);
	}
	return node;
}

501. 二叉搜索树中的众数

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

结点左子树中所含结点的值小于等于当前结点的值
结点右子树中所含结点的值大于等于当前结点的值
左子树和右子树都是二叉搜索树
例如:
给定 BST [1,null,2,2],

   1
    \
     2
    /
   2

返回[2].

递归法:
对于二叉搜索树来说,中序遍历就可以将节点进行从小到大排列,使用中序遍历,对于每个元素进行记录,然后对于如果后面出现的元素比前面的要大,我们就要对最大的元素进行更新。

class Solution{
	public:
		int count;
		int maxcount;
		TreeNode *pre;
		vector<int> result;
		void searchBST(TreeNode *cur){
			if(cur==NULL) return;
			searchBST(cur->left);
			if(pre==NULL){
				count=1;
			}
			else if(pre->val==cur->val){
				count++;
			}else{
				count=1;
			}
			pre=cur;
			if(count==maxcount){
				result.push_back(cur->val);
			}
			if(count>maxcount){
				maxcount=count;
				result.clear();
				result.push_back(cur->val);
			}
			searchBST(cur->right);
		}
		vector<int>findMode(TreeNode *root){
			count=0;
			maxcount=0;
			result.clear();
			searchBST(root);
			return result;
		}
}

对于一个任意的二叉树,我们需要统计每个节点出现的频率,然后将频率进行排列,取最高的,然后对应的数值就是众数

class Solution{
	public:
		void searchBST(TreeNode* cur, unordered_map<int,int>&map){
			if(cur==NULL) return;
			map[cur->val]++;
			searchBST(cur->left,map);
			searchBST(cur->right,map);
		}
		bool static cmp(const pair<int,int> &a, const pair<int,int> &b){
			return a.second>b.second;
		}
		vector<int> findMode(TreeNode *root){
			unordered_map<int,int> map; //key,value,这里就表示元素和出现频率
			vector<int> result;
			if(root==NULL) return result;
			searchBST(root,map);
			vector<pair<int,int>> vec(map.begin(),map.end()); //转换成数组
			sort(vec.begin(),vec,end(),cmp);//将频率从大到小排列
			result.push_back(vec[0].first);
			for(int i=1;i<vec.size();i++){ //fisrt:数值, second: 频率
				if(vec[i].second==vec[0].second) result.push_back(vec[i].first);
				else break;
			}
			return result;
		}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值