1.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:先通过先序遍历找到两棵树根节点相等得节点,然后进行从这两个节点开始递归判断是不是子结构。
class Solution { public: bool HasSubtree(TreeNode* root1, TreeNode* root2) { bool result = false; if(root1 != NULL && root2 != NULL){ if(root1->val == root2->val){ result = DoesTree1HaveTree2(root1,root2); } if(!result){result = HasSubtree(root1->left, root2);} if(!result){result = HasSubtree(root1->right, root2);} } return result; } bool DoesTree1HaveTree2(TreeNode* root1, TreeNode* root2) { if(root1 == NULL && root2 != NULL) return false; if(root2 == NULL) return true; if(root1->val != root2->val) return false; return DoesTree1HaveTree2(root1->left, root2->left) && DoesTree1HaveTree2(root1->right, root2->right); } };
2.求一棵树的镜像
思路:先序遍历这棵树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点。
class Solution { public: void Mirror(TreeNode *pRoot) { if(!pRoot)return; if(pRoot->left==NULL&&pRoot->right==NULL)return; TreeNode* tmp=pRoot->left; pRoot->left=pRoot->right; pRoot->right=tmp; if(pRoot->left)Mirror(pRoot->left); if(pRoot->right)Mirror(pRoot->right); } };
3.给你一个序列,判断该序列是不是二叉排序树的后序遍历
思路:后序遍历中最后一个数字是树得跟节点的值,序列前面的数可以分成两部分,前一部分比该值小,后一部分比该值大。
class Solution { public: bool VerifySquenceOfBST(vector<int> sequence) { if(sequence.size()==0)return false; return help(sequence,0,sequence.size()-1); } bool help(vector<int>sequence,int start,int end){ if(start>=end)return true; int i=start; int value=sequence[end]; while(sequence[i]<value){ i++; } for(int j=i;j<end;j++){ if(sequence[j]<value){ return false; } } return help(sequence,start,i-1)&&help(sequence,i,end-1); } };
4.二叉树中和为某一值的路径
思路:dfs,记住root->left前一定要先判断(if(root->left))
class Solution { public: vector<vector<int> > FindPath(TreeNode* root,int expectNumber) { vector<int>out; vector<vector<int>>res; if(!root)return res; help(root,expectNumber,res,out); return res; } void help(TreeNode* root,int number,vector<vector<int>>&res,vector<int>&out){ out.push_back(root->val); if(root->left==NULL&&root->right==NULL){ if(number==root->val)res.push_back(out); } if(root->left){ help(root->left,number-root->val,res,out); } if(root->right){ help(root->right,number-root->val,res,out); } out.pop_back(); } };
5.树的深度(非递归)
思路:利用队列层次遍历
class Solution { public: int TreeDepth(TreeNode* pRoot) { if(!pRoot)return 0; queue<TreeNode*>q; q.push(pRoot); int depth=0; while(!q.empty()){ int size=q.size(); for(int i=0;i<size;i++){ if(q.front()->left)q.push(q.front()->left); if(q.front()->right)q.push(q.front()->right); q.pop(); } depth++; } return depth; } };
6.判断一棵二叉树是不是平衡二叉树
思路:利用后序遍历从下到上求每个节点左右子树的高度差,这样可以省去一些重复节点的遍历
class Solution { public: bool IsBalanced_Solution(TreeNode* pRoot) { bool flag=true; int tmp=getDepth(pRoot,flag); return flag; } int getDepth(TreeNode* root,bool &flag){ if(!root)return 0; int left=getDepth(root->left,flag); int right=getDepth(root->right,flag); if(abs(left-right)>1)flag=false; return left>right?left+1:right+1; } };
7.按之字形打印二叉树
思路:利用两个栈来接收每行的节点,并且用一个标志位判断是从左向右还是从又向左
class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { vector<vector<int>>res; if(!pRoot)return res; vector<int>temp; int flag=0;//0是向右,1是向左 stack<TreeNode*>s1; stack<TreeNode*>s2; s1.push(pRoot); while(!s1.empty()||!s2.empty()){ if(!s1.empty()){ const int size=s1.size(); for(int i=0;i<size;i++){ if(flag==0){ if(s1.top()->left)s2.push(s1.top()->left); if(s1.top()->right)s2.push(s1.top()->right); } else{ if(s1.top()->right)s2.push(s1.top()->right); if(s1.top()->left)s2.push(s1.top()->left); } temp.push_back(s1.top()->val); s1.pop(); } res.push_back(temp); temp.clear(); flag=!flag; } else if(!s2.empty()){ const int size=s2.size(); for(int i=0;i<size;i++){ if(flag==0){ if(s2.top()->left)s1.push(s2.top()->left); if(s2.top()->right)s1.push(s2.top()->right); } else{ if(s2.top()->right)s1.push(s2.top()->right); if(s2.top()->left)s1.push(s2.top()->left); } temp.push_back(s2.top()->val); s2.pop(); } res.push_back(temp); temp.clear(); flag=!flag; } } return res; } };
8.给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。
思路:二叉搜索树的中序遍历是排序的,我们根据中序遍历找到第k个小个节点。
class Solution { public: TreeNode* KthNode(TreeNode* pRoot, int k) { if(!pRoot)return NULL; stack<TreeNode*>ss; TreeNode* cur=pRoot; int count=0; while(cur||!ss.empty()){ if(cur){ ss.push(cur); cur=cur->left; } else{ cur = ss.top(); count++; if(count==k) return cur; ss.pop(); cur = cur->right; } } return NULL; } };
9.二叉树中的最大路径和(思路:参考https://www.cnblogs.com/grandyang/p/4280120.html)
class Solution { public: int maxv=INT_MIN; int maxPathSum(TreeNode* root) { if(root==NULL) return 0; calc(root); return maxv; } int calc(TreeNode* root) { if(root==NULL) return 0; int temp=root->val; int lmaxsum=calc(root->left); int rmaxsum=calc(root->right); if(lmaxsum>0) temp+=lmaxsum; if(rmaxsum>0) temp+=rmaxsum; if(temp>maxv) maxv=temp; //返回以当前节点为根节点的子树的和 return max(root->val,max(root->val+lmaxsum,root->val+rmaxsum));//因为对于当前节点root来说,它的上一个节点只可能选择root+left与root+right中的最大值 } };
10.二叉树中的最近公共祖先