今天的刷题内容是二叉树和递归的应用:
二叉树中的很多题目都可以通过递归的方法进行调用,比如简单的前序遍历,中序遍历,后续遍历等算法的实现,递归调用主要是两个内容,一个是递归的终止条件,另一个是递归循环体;废话不多说直接使用leetcode中的题来练手
leetcode104,求一个二叉树的最大深度,
class Solution { public: int maxDepth(TreeNode* root) { if(root==NULL){ return 0;//递归的停止条件 } int left_max=maxDepth(root->left); int right_max=maxDepth(root->right); return max(left_max,right_max)+1; } };
提交后运行的时间为8ms;
最大深度还可以通过层序遍历的方式,还可以通过dfs的方式来实现
层序遍历的代码如下:
int maxDepth(TreeNode* root) { //方法一使用层序遍历的方式 进行 统计相应的层数 //方法二 使用的是递归的方式进行相应的统计 非递归方式统树的高度 //方法三采用dfs的方式 深度搜索的方式 if(root==NULL){ return 0; } queue<TreeNode*> qq; qq.push(root); int step=0; while(!qq.empty()){ int size=qq.size(); int i=0; while(i<size){ TreeNode* node=qq.front(); qq.pop(); if(node->left){ qq.push(node->left); } if(node->right){ qq.push(node->right); } i++; } step++; } return step; }
采用dfs的方式代码如下:
int maxDepth(TreeNode* root){ if(root==NULL){ return 0; } int length=dfs(root); return length; } int dfs(TreeNode* root){ if(root==NULL){ return 0; } int l=dfs(root->left); int r=dfs(root->right); return max(l,r)+1; }
类似的Leetcode111
class Solution { public: int minDepth(TreeNode* root) { //求解二叉树中最小深度 if(root==NULL){ return 0; } // int left_num=minDepth(root->left); // int right_num=minDepth(root->right); // return min(left_num,right_num)+1; //如果直接使用这样的递归算法,会导致出错,原因就是 题目要求是从根节点到叶子节点的路径,对于不平衡的树会导致出错,递归的停止条件需要改变 if(root->left==NULL&&root->right==NULL){ return 1; } if(root->left==NULL&&root->right!=NULL){ return minDepth(root->right)+1; } if(root->right==NULL&&root->left!=NULL){ return minDepth(root->left)+1; } int left_num=minDepth(root->left); int right_num=minDepth(root->right); return min(left_num,right_num)+1; } };
leetcode226:反转一棵二叉树;
class Solution { public: TreeNode* invertTree(TreeNode* root) { if(root==NULL){ return NULL;//书写循环终止条件 } // if(root->left==NULL&&root->right==NULL){ // return root; // }不需要添加 因为返回的就是root // TreeNode* tree_left=root->left; // TreeNode* tree_right=root->right; invertTree(root->left); invertTree(root->right); swap(root->left,root->right); return root; } };
leetcode100:判断两棵树是否是一样的树;
class Solution { public: bool isSameTree(TreeNode* p, TreeNode* q) { //递归调用来实现,或者是采用先序遍历方式来实现保存至一个vector中,然后实现 //递归的终止条件 if(p==NULL&&q==NULL){ return true; } if(p==NULL||q==NULL){ return false; } if(p->val!=q->val){ return false; } if((isSameTree(p->left,q->left))&&isSameTree(p->right,q->right)){ return true; } return false; } };
leetcode101:判断一棵树是否是对称树;
class Solution { public: bool isSymmetric(TreeNode* root) { //采用递归的方法来实现; //首先是循环的停止条件 if(root==NULL){ return true; } if(root->left==NULL&&root->right==NULL){ return true; } if(root->left==NULL||root->right==NULL){ return false; } return isSymmetric2(root->left,root->right); } bool isSymmetric2(TreeNode* left,TreeNode* right){ if(left==NULL&&right==NULL){ return true; } if(left==NULL||right==NULL){ return false; } if(left->val!=right->val){ return false; } return isSymmetric2(left->left,right->right)&&isSymmetric2(left->right,right->left); } };
leetcode110:判断一棵树是否是平衡树,什么是平衡树(平衡树就是每一层的两个结点的深度最大相差1);
class Solution { public: bool isBalanced(TreeNode* root) { //首先递归的停止条件 if(root==NULL){ return true; } if(root->left==NULL&&root->right==NULL){ return true; } //得到每个结点的从根节点到叶节点的路径长度; int left_num=length(root->left); int right_num=length(root->right); if(abs(left_num-right_num)==1||abs(left_num-right_num)==0){ return isBalanced(root->left)&&isBalanced(root->right);//如果当前层是平衡树,那么继续比较下一层 } else{ return false; } } int length(TreeNode * root){ if(root==NULL){ return 0; } int leftNum=length(root->left); int rightNum=length(root->right); return max(leftNum,rightNum)+1; } };
leetcode112: 判断是否有路径和为sum的路径;最主要的就是书写递归停止的条件;
class Solution { public: bool hasPathSum(TreeNode* root, int sum) { //递归的停止条件 if(root==NULL){ return false; } if(root->left==NULL&&root->right==NULL&&root->val==sum){ return true; } if(root->left==NULL&&root->right==NULL&&root->val!=sum){ return false; } if((root->left==NULL||root->right==NULL)&&root->val==sum){ return false; } return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val); } };
leetcode222:求一个完全二叉树的结点的个数;
首先需要知道什么是完全二叉树:
class Solution { public: int countNodes(TreeNode* root) { //什么是完全二叉树,完全二叉树是指除了最下面一层,其余层的结点都是满的,最下面一层的二叉树分布在最左边的位置处; //循环停止条件 // if(root==NULL){ // return 0; // } // if(root->left==NULL&&root->right==NULL){ // return 1; // } // if(root->left==NULL||root->right==NULL){ // return 2; // } // return countNodes(root->left)+countNodes(root->right)+1;//这个方法没有体现完全二叉树的特性,所以没有accept,原因在于过多的递归导致系统栈溢出 if(root==NULL) return 0; int leftDepth=0; int rightDepth=0; for(TreeNode* node=root;node!=NULL;node=node->left) leftDepth++; for(TreeNode* node=root;node!=NULL;node=node->right) rightDepth++; if(leftDepth==rightDepth) return (1<<leftDepth)-1; else return countNodes(root->left)+countNodes(root->right)+1; } };
leetcode404:计算出所有左子节点的和,这道题的递归条件有所不同,所以递归的停止条件比较复杂;刚开始的时候没有想出来;
class Solution { public: int sumOfLeftLeaves(TreeNode* root) { if(root==NULL){ return 0; } if(root->left!=NULL&&root->left->left==NULL&&root->left->right==NULL){ return root->left->val+sumOfLeftLeaves(root->right); } return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right); } };
leetcode 257: 从递归中返回一个vector类型的数据结构的递归问题;
class Solution { public: vector<string> binaryTreePaths(TreeNode* root) { //相对比较复杂的递归停止条件的习题 //可以知道原函数的递归的返回值是vector类型的数据,所以每一次返回的都是vector<string>数据 vector<string> ans; if(root==NULL){ return ans; } if(root->left==NULL&&root->right==NULL){ ans.push_back(to_string(root->val)); return ans; } vector<string> left_string=binaryTreePaths(root->left); vector<string> right_string=binaryTreePaths(root->right); for(int i=0;i<left_string.size();i++){ ans.push_back(to_string(root->val)+"->"+left_string[i]); } for(int j=0;j<right_string.size();j++){ ans.push_back(to_string(root->val)+"->"+right_string[j]); } return ans; } };
leetcode113:这道题是上一道题的扩展,只不过这道题的是求出相应的路径,并且是使用vector,操作上会有一点麻烦,而且还必须是从根节点到叶子节点的路径;递归的停止条件比较复杂;
class Solution { public: vector<vector<int>> pathSum(TreeNode* root, int sum) { vector<vector<int>> ans; if(root==NULL){ return ans; } vector<int> temp; if(root->left==NULL&&root->right==NULL&&root->val==sum){ temp.push_back(root->val); ans.push_back(temp); return ans; } if((root->left==NULL)&&root->val!=sum){//如果找不到要怎么办,首先需要书写一个函数判断一下 vector<vector<int>> right_ans=pathSum(root->right,sum-root->val); for(int i=0;i<right_ans.size();i++){ vector<int> temp=right_ans[i]; vector<int>::iterator it=temp.begin(); temp.insert(it,root->val); ans.push_back(temp); } return ans; } if((root->right==NULL)&&root->val!=sum){//如果找不到要怎么办,首先需要书写一个函数判断一下 vector<vector<int>> left_ans=pathSum(root->left,sum-root->val); for(int i=0;i<left_ans.size();i++){ vector<int> temp=left_ans[i]; vector<int>::iterator it=temp.begin(); temp.insert(it,root->val); ans.push_back(temp); } return ans; } vector<vector<int>> right_ans2=pathSum(root->right,sum-root->val); for(int i=0;i<right_ans2.size();i++){ vector<int> temp=right_ans2[i]; vector<int>::iterator it=temp.begin(); temp.insert(it,root->val); ans.push_back(temp); } vector<vector<int>> left_ans2=pathSum(root->left,sum-root->val); for(int i=0;i<left_ans2.size();i++){ vector<int> temp=left_ans2[i]; vector<int>::iterator it=temp.begin(); temp.insert(it,root->val); ans.push_back(temp); } return ans; } };