1.leetcode 513.找树左下角的值
这道题如果用递归法的话,可能会比较难,但是如果用迭代法里面的层序遍历,那就非常简单了,甚至可以套用模板并加以修改一点点就行了。
第一种解法:递归法
咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?
没有这么简单,一直向左遍历到最后一个,它未必是最后一行啊。
我们来分析一下题目:在树的最后一行找到最左边的值。
首先要是最后一行,然后是最左边的值。
如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int maxDepth=INT_MIN;
int result=0;
void traversal(TreeNode* node,int depth){
if(node->left==NULL&&node->right==NULL){
if(depth>maxDepth){
maxDepth=depth;
result=node->val;
}
return;
}
if(node->left){
traversal(node->left,depth+1);
}
if(node->right){
traversal(node->right,depth+1);
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root,0);
return result;
}
};
第二种解法:迭代法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int result=0;
if(root==NULL) return 0;
que.push(root);
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;
}
};
2.leetcode 112.路径总和
这道题用的是递归法,用的是深度优先搜索,这道题用前中后序遍历其实都可以。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public://count如果为0,就表示找到了符合条件的路径
bool traversal(TreeNode* current,int count){
//遇到叶子节点
if(current->left==NULL&¤t->right==NULL&&count==0) return true;
if(current->left==NULL&¤t->right==NULL&&count!=0) return false;
if(current->left){
count-=current->left->val;//递归,处理节点
if(traversal(current->left,count)) return true;
count+=current->left->val;//回溯,撤销处理结果
}
if(current->right){
count-=current->right->val;//递归,处理节点
if(traversal(current->right,count)) return true;
count+=current->right->val;//回溯,撤销处理结果
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==NULL) return false;
return traversal(root,targetSum-root->val);
}
};
3.leetcode 113.路径总和II
这道题也是上一道题的一个补充。写完上一道题随便做了一下这道题。
这道题和上一道题的区别在于,上一道题是要找出二叉树中一条路径等于targetSum就可以了,就return true,否则return false。而这道题是要在这个二叉树中找出所有等于targetSum的路径,然后返回这个路径的所有的数字,所以这道题的返回值是一个二维数组。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
//递归函数不要返回值,因为我们要遍历整个二叉树
//这里的count跟上一道题的count是一个意思
void traversal(TreeNode* current,int count){
if(current->left==NULL&¤t->right==NULL&&count==0){
result.push_back(path);
return;
}
if(current->left==NULL&¤t->right==NULL&&count!=0) return;
if(current->left){
path.push_back(current->left->val);
count-=current->left->val;
traversal(current->left,count);
count+=current->left->val;
path.pop_back();
}
if(current->right){
path.push_back(current->right->val);
count-=current->right->val;
traversal(current->right,count);
count+=current->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root==NULL) return result;
path.push_back(root->val);
traversal(root,targetSum-root->val);
return result;
}
};
4.leetcode 106.从中序与后序遍历序列构造二叉树
这道题算是比较难的二叉树的题目了。这道题如果单单分析的话,稍微动一点脑筋就可以分析出来,但是如果要用代码自己实现出来的话,还是比较难的。
说到一层一层切割,就应该想到了递归。
来看一下一共分几步:
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点。
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)第五步:切割后序数组,切成后序左数组和后序右数组。
第六步:递归处理左区间和右区间。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
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 delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++){
if(inorder[delimiterIndex]==rootValue) break;
}
//切割中序数组
//左闭右开区间
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
//postorder舍弃末尾元素
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);
}
};
5.leetcode 105.从前序与中序遍历序列构造二叉树
这道题的思路跟上一道题的思路是一样的,只是有些地方稍微改动了一下。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* traversal(vector<int>& inorder,int inorderBegin,int inorderEnd,vector<int>& preorder,int preorderBegin,int preorderEnd){
if(preorderBegin==preorderEnd) return NULL;
int rootValue=preorder[preorderBegin];//注意这里是用preorderBegin,不能用0
TreeNode* root=new TreeNode(rootValue);
if(preorderEnd-preorderBegin==1) return root;
int delimiterIndex;
for(delimiterIndex=inorderBegin;delimiterIndex<inorderEnd;delimiterIndex++){
if(inorder[delimiterIndex]==rootValue) break;
}
//切割中序数组
//中序左区间,左闭右开
int leftInorderBegin=inorderBegin;
int leftInorderEnd=delimiterIndex;
//中序右区间。左闭右开
int rightInorderBegin=delimiterIndex+1;
int rightInorderEnd=inorderEnd;
//切割前序数组
//前序左区间,左闭右开
int leftPreorderBegin=preorderBegin+1;
int leftPreorderEnd=preorderBegin+1+delimiterIndex-inorderBegin;//终止位置是起始位置加上中序左区间的大小size
//前序右区间,左闭右开
int rightPreorderBegin=preorderBegin+1+(delimiterIndex-inorderBegin);
int rightPreorderEnd=preorderEnd;
root->left=traversal(inorder,leftInorderBegin,leftInorderEnd,preorder,leftPreorderBegin,leftPreorderEnd);
root->right=traversal(inorder,rightInorderBegin,rightInorderEnd,preorder,rightPreorderBegin,rightPreorderEnd);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(inorder.size()==0||preorder.size()==0) return NULL;
//参数都坚持左闭右开原则
return traversal(inorder,0,inorder.size(),preorder,0,preorder.size());
}
};
温馨提示:看代码的时候一定要仔细看,不然的话容易看错代码,可能一个参数的改变,答案就错了。