总结:解决和树有关的问题的时候,一般用到的方法有两种:深度优先搜索(DFS)和广度优先搜索(BFS)。广度优先搜索实质上就是层次遍历,每遍历完一层的所有节点才开始遍历下一层节点;深度优先搜索则是按分支去遍历树,一条分支遍历完再遍历下一条分支,深度优先搜索一般是用递归来实现。下面题目中题目3和题目4可以用BFS解决;题目1,题目2,题目3,题目5可以用DFS解决。
题目1:二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
思路:使用后序遍历,先遍历左子树得到左子树深度,再遍历右子树得到右子树深度;之后取左右子树深度中的较大值再加上根节点就是二叉树的最大深度。
int maxDepth(TreeNode* root)
{
if(root==NULL)
{
return 0;
}
else
{
int Llen = maxDepth(root->left);
int Rlen = maxDepth(root->right);
return (Llen>Rlen?Llen:Rlen)+1;
}
}
题目2:验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
1.节点的左子树只包含小于当前节点的数。
2.节点的右子树只包含大于当前节点的数。
3.所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:
2
/ \
1 3
输出: true
示例 2:
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
思路:二叉搜索树的特征是中序遍历一棵二叉搜索树得到的序列是有序序列,所以先对二叉搜索树进行中序遍历并记录遍历得到的序列,之后判断这个序列是否为有序序列。
//中序遍历
void LDR(TreeNode* root,vector<int>& arr)
{
if(root!=NULL)
{
LDR(root->left,arr);
arr.push_back(root->val);
LDR(root->right,arr);
}
}
bool isValidBST(TreeNode* root)
{
vector<int> arr;
LDR(root,arr);
for(int i=1;i<arr.size();i++)
if(arr[i]<=arr[i-1])
return false;
return true;
}
题目3:对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树[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
思路:判断是否为对称二叉树就是判断每层第一个节点和最后一个节点,第二个节点和倒数第二个节点等等相对应的节点是否相等。可以用DFS和BFS两种方法来解决问题。用BFS就是每次获得一层的所有节点,然后判断这些节点是否对称。用DFS就是按自两侧到中央,自上层到下层的顺序递归判断。下面实现的就是DFS方法。
bool judge(TreeNode* node1,TreeNode* node2)
{
if(!node1&&!node2)
return true;
if(!node1||!node2||(node1->val!=node2->val))
return false;
return judge(node1->left,node2->right)&&judge(node1->right,node2->left);
}
bool isSymmetric(TreeNode* root)
{
if(!root)
return true;
return judge(root->left,root->right);
}
题目4:二叉树的层次遍历
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
思路:从最顶层(即根节点)开始,依次将该层所有节点的val放入结果列表中,并且将该层节点的左右子节点放入下一层节点列表中,作为下一层遍历的节点,即下一层所要遍历的节点是在上一层遍历过程中产生的。
vector<vector<int> > levelOrder(TreeNode* root)
{
vector<vector<int> > nums;
if(root==NULL)
return nums;
queue<TreeNode*> level;
level.push(root);
while(level.size()!=0)
{
int len = level.size();
vector<int> num;
//处理一层的节点
for(int i=0;i<len;i++)
{
TreeNode* node = level.front();
level.pop();
num.push_back(node->val);
//为了顺序正常,先左后右
if(node->left!=NULL)
level.push(node->left);
if(node->right!=NULL)
level.push(node->right);
}
nums.push_back(num);
}
return nums;
}
题目5:将有序数组转换为二叉搜索树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
思路:本质是构造一个二叉排序树,二叉排序树是一棵特殊的二叉搜索树,在二叉搜索树的基础上,要求其每个节点的左右两个子树的高度差的绝对值不超过1,即左右子树节点个数相同(奇数个节点)或相差1(偶数个节点),因此二叉排序树中根节点是有序序列的中点,其左子节点是前半部分序列的中点,其右子节点是后半部分序列中点,实质上就是对二分搜索的应用。
TreeNode* creatBST(vector<int> nums,int left,int right)
{
if(left>right)
return NULL;
int mid = (left+right)/2;
TreeNode* node = new TreeNode(nums[mid]);
node->left = creatBST(nums,left,mid-1);
node->right = creatBST(nums,mid+1,right);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums)
{
return creatBST(nums,0,nums.size()-1);
}