二叉树
字符串转int
(5条消息) c++中的atoi()和stoi()函数的用法和区别_鸡啄米的时光机的博客-CSDN博客_stoi
int转字符串
递归三部曲,1确定递归函数参数和返回值;2确定终止条件;3确定单层逻辑
三种基本遍历,不仅递归要会,用栈迭代遍历也要会
144. 二叉树的前序遍历 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 void f(TreeNode* root,vector<int>&result){ 4 if(!root) 5 return ; 6 result.push_back(root->val); 7 f(root->left,result); 8 f(root->right,result); 9 } 10 vector<int> preorderTraversal(TreeNode* root) { 11 vector<int> result; 12 f(root,result); 13 return result; 14 } 15 };
94. 二叉树的中序遍历 - 力扣(LeetCode) (leetcode-cn.com)
145. 二叉树的后序遍历 - 力扣(LeetCode) (leetcode-cn.com)
102. 二叉树的层序遍历 - 力扣(LeetCode) (leetcode-cn.com)
这道题忘记队列的size()方法可以获取长度了
class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> ans; queue<TreeNode*> q; if(!root) return ans; q.push(root); while(!q.empty()){ vector<int> a; int n = q.size();//划重点队列大小会变,所以赶紧存下来 for(int i=0;i<n;++i){ TreeNode* t= q.front(); a.push_back(t->val); q.pop(); if(t->left) q.push(t->left); if(t->right) q.push(t->right); } ans.push_back(a); } return ans; } };
226. 翻转二叉树 - 力扣(LeetCode) (leetcode-cn.com)
class Solution { public: void f(TreeNode* &root){ if(!root) return ; swap(root->left,root->right); f(root->left); f(root->right); } TreeNode* invertTree(TreeNode* root) { f(root); return root; } };
101. 对称二叉树 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 bool f(TreeNode* root1,TreeNode* root2){ 4 if(!root1&&!root2) 5 return true; 6 else if(!root1&&root2) 7 return false; 8 else if(root1&&!root2) 9 return false; 10 else if(root1->val!=root2->val) 11 return false; 12 return f(root1->left,root2->right)&&f(root1->right,root2->left); 13 } 14 bool isSymmetric(TreeNode* root) { 15 if(!root) 16 return true; 17 return f(root->left,root->right); 18 } 19 };
104. 二叉树的最大深度 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 int getDepth(TreeNode* root,int depth){ 4 if(!root) 5 return depth; 6 return max(getDepth(root->left,depth+1),getDepth(root->right,depth+1)); 7 } 8 int maxDepth(TreeNode* root) { 9 return getDepth(root,0); 10 } 11 };
111. 二叉树的最小深度 - 力扣(LeetCode) (leetcode-cn.com)
class Solution { public: int getDepth(TreeNode* root,int depth){ if(!root) return 1e5; if(root&&!root->left&&!root->right) return depth+1; return min(getDepth(root->left,depth+1),getDepth(root->right,depth+1)); } int minDepth(TreeNode* root) { if(!root) return 0 ; return getDepth(root,0); } };
110. 平衡二叉树 - 力扣(LeetCode) (leetcode-cn.com)
自顶而下解法,最差情况一条链O(n^2)
1 class Solution { 2 public: 3 int getDepth(TreeNode* root,int depth){ 4 if(!root) 5 return depth; 6 return max(getDepth(root->left,depth+1),getDepth(root->right,depth+1)); 7 } 8 bool isBalanced(TreeNode* root) { 9 if(!root) 10 return true; 11 if(abs(getDepth(root->left,0)-getDepth(root->right,0))>1){//符号与)位置 12 return false; 13 } 14 15 return isBalanced(root->left)&&isBalanced(root->right); 16 } 17 };
后序遍历O(n)深度,root值最小为1
1 class Solution { 2 public: 3 bool result = true; 4 int getDepth(TreeNode* root,int depth){ 5 if(!root) 6 return depth; 7 int leftDepth = getDepth(root->left,depth+1); 8 int rightDepth = getDepth(root->right,depth+1); 9 if(abs(leftDepth-rightDepth)>1){ 10 result =false; 11 return 0; 12 } 13 return max(leftDepth,rightDepth); 14 } 15 bool isBalanced(TreeNode* root) { 16 getDepth(root,0); 17 return result; 18 } 19 };
后续遍历O(n)高度,root值最大
1 class Solution { 2 public: 3 int getHeight(TreeNode* root){//高度写法,根的高度最高数值最大,最底下叶子节点为1,和深度反着,深度是根这为1,叶子最底下节点最大。看那个+1是从上往下传还是从下往上 4 if(!root) 5 return 0; 6 int leftHeight = getHeight(root->left); 7 int rightHeight = getHeight(root->right); 8 if(leftHeight==-1||rightHeight==-1||abs(leftHeight-rightHeight)>1){//中间子树出错,要传递错误到根,和全局变量写法不一样 9 return -1; 10 } 11 return max(leftHeight,rightHeight)+1; 12 } 13 bool isBalanced(TreeNode* root) { 14 return getHeight(root)!=-1; 15 } 16 };
257. 二叉树的所有路径 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 vector<string> result; 4 void f(TreeNode* root,string s){ 5 if(!root) 6 return ; 7 if(root!=nullptr&&root->left==nullptr&&root->right==nullptr){ 8 s = s==""?to_string(root->val):s+="->"+to_string(root->val); 9 result.push_back(s); 10 s = ""; 11 return ; 12 } 13 s = s==""?to_string(root->val):s+="->"+to_string(root->val); 14 f(root->left,s); 15 f(root->right,s); 16 } 17 vector<string> binaryTreePaths(TreeNode* root) { 18 string s = ""; 19 f(root,s); 20 return result; 21 } 22 };
112. 路径总和 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 bool result = false; 4 void f(TreeNode* root, int targetSum){ 5 if(root==nullptr) 6 return ; 7 targetSum -= root->val; 8 if(root->left==nullptr&&root->right==nullptr&&targetSum == 0){ 9 result = true; 10 return ; 11 } 12 f(root->left,targetSum); 13 f(root->right,targetSum); 14 } 15 bool hasPathSum(TreeNode* root, int targetSum) { 16 if(!root) 17 return false; 18 f(root,targetSum); 19 return result; 20 } 21 };
113. 路径总和 II - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 vector<vector<int>> result; 4 void f(TreeNode* root, int targetSum,vector<int>vec){ 5 if(root==nullptr) 6 return ; 7 targetSum -= root->val; 8 vec.push_back(root->val); 9 if(root->left==nullptr&&root->right==nullptr&&targetSum == 0){ 10 result.push_back(vec); 11 return ; 12 } 13 f(root->left,targetSum,vec); 14 f(root->right,targetSum,vec); 15 } 16 vector<vector<int>> pathSum(TreeNode* root, int targetSum) { 17 vector<int> vec; 18 f(root,targetSum,vec); 19 return result; 20 } 21 };
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution {//先后续遍历找根,再中序遍历划分,循环这个步骤找根划分。特征,左子树所有元素是连续的,右子树也是,中序遍历划分后得出长度,划分后续遍历 2 public: 3 TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { 4 if(inorder.size()==0||postorder.size()==0) 5 return nullptr; 6 TreeNode* root = new TreeNode(postorder[postorder.size()-1]); 7 vector<int>leftInorder; 8 vector<int>rightInorder; 9 vector<int>leftPostorder; 10 vector<int>rightPostorder; 11 int i; 12 for(i=0;i<inorder.size()-1;i++){//左右要分开,因为后续遍历舍弃最后一个数字,中序遍历舍弃根节点数据 13 if(inorder[i]==root->val){ 14 break; 15 } 16 leftInorder.push_back(inorder[i]); 17 } 18 for(i++;i<inorder.size();i++){ 19 rightInorder.push_back(inorder[i]); 20 } 21 int j; 22 for(j=0;j<postorder.size()-1;j++){ 23 if(j<leftInorder.size()) 24 leftPostorder.push_back(postorder[j]); 25 else 26 rightPostorder.push_back(postorder[j]); 27 } 28 root->left = buildTree(leftInorder,leftPostorder); 29 root->right = buildTree(rightInorder,rightPostorder); 30 return root; 31 } 32 };
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution {//先后续遍历找根,再中序遍历划分,循环这个步骤找根划分。特征,左子树所有元素是连续的,右子树也是,中序遍历划分后得出长度,划分后续遍历 2 public: 3 TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { 4 if(inorder.size()==0||preorder.size()==0) 5 return nullptr; 6 TreeNode* root = new TreeNode(preorder[0]); 7 vector<int>leftInorder; 8 vector<int>rightInorder; 9 vector<int>leftPreorder; 10 vector<int>rightPreorder; 11 int i; 12 for(i=0;i<inorder.size()-1;i++){//左右要分开,因为后续遍历舍弃最后一个数字,中序遍历舍弃根节点数据 13 if(inorder[i]==root->val){ 14 break; 15 } 16 leftInorder.push_back(inorder[i]); 17 } 18 for(i++;i<inorder.size();i++){ 19 rightInorder.push_back(inorder[i]); 20 } 21 int j; 22 for(j=1;j<preorder.size();j++){ 23 if(j<=leftInorder.size()) 24 leftPreorder.push_back(preorder[j]); 25 else 26 rightPreorder.push_back(preorder[j]); 27 } 28 root->left = buildTree(leftPreorder,leftInorder); 29 root->right = buildTree(rightPreorder,rightInorder); 30 return root; 31 } 32 };
98. 验证二叉搜索树 - 力扣(LeetCode) (leetcode-cn.com)
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 * }; 11 */ 12 class Solution {//老想着一步到位,中序遍历存储上一次值,这样比较。不会。还是存储所有数据到数组再升序判断简单。还有等于妈的。。 13 public: 14 vector<int> res; 15 void f(TreeNode* root){ 16 if(!root) 17 return ; 18 f(root->left); 19 res.push_back(root->val); 20 f(root->right); 21 } 22 bool isValidBST(TreeNode* root) {//中序遍历升序 23 f(root); 24 for(int i=0;i<res.size()-1;i++){ 25 if(res[i]>=res[i+1]) 26 return false; 27 } 28 return true; 29 } 30 };
530. 二叉搜索树的最小绝对差 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 vector<int> res; 4 void f(TreeNode* root){ 5 if(!root) 6 return ; 7 f(root->left); 8 res.push_back(root->val); 9 f(root->right); 10 } 11 int getMinimumDifference(TreeNode* root) { 12 f(root); 13 int minn = 1e5; 14 for(int i=0;i<res.size()-1;i++){ 15 minn = min(minn,res[i+1]-res[i]); 16 } 17 return minn; 18 } 19 };
501. 二叉搜索树中的众数 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 unordered_map<int,int> map; 4 void f(TreeNode* root){ 5 if(root==nullptr) 6 return; 7 map[root->val]++; 8 f(root->left); 9 f(root->right); 10 11 } 12 bool static cmp(const pair<int,int>a,const pair<int,int>b){ 13 return a.second>b.second; 14 } 15 vector<int> findMode(TreeNode* root) { 16 f(root); 17 vector<pair<int,int>>vec(map.begin(),map.end()); 18 sort(vec.begin(),vec.end(),cmp); 19 vector<int>result; 20 result.push_back(vec[0].first); 21 for(int i=1;i<vec.size();i++){ 22 if(vec[i].second==vec[0].second) 23 result.push_back(vec[i].first); 24 else 25 break; 26 } 27 return result; 28 } 29 };
236. 二叉树的最近公共祖先 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 TreeNode* f(TreeNode* root, TreeNode* p, TreeNode* q){ 4 if(root==NULL){ 5 return root; 6 } 7 TreeNode* left = f(root->left,p,q); 8 TreeNode* right = f(root->right,p,q); 9 if(((left!=NULL)&&(right!=NULL))||((left!=NULL)&&(root==p||root==q))||((root==p||root==q)&&(right!=NULL))){ 10 return root; 11 } 12 else if(left!=NULL) 13 root = left; 14 else if(right!=NULL) 15 root = right; 16 else if(root!=p&&root!=q) 17 root = NULL; 18 return root; 19 } 20 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 21 return f(root,p,q); 22 } 23 };
235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution {//二叉搜索树特殊性,左小右大 2 public: 3 TreeNode* f(TreeNode* root, TreeNode* p, TreeNode* q){ 4 if(root==NULL){ 5 return root; 6 } 7 if(root->val>q->val&&root->val>p->val) 8 return f(root->left,p,q); 9 if(root->val<p->val&&root->val<q->val) 10 return f(root->right,p,q); 11 return root; 12 } 13 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 14 return f(root,p,q); 15 } 16 };
701. 二叉搜索树中的插入操作 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 TreeNode* f(TreeNode* root,int val){ 4 if(root==nullptr){ 5 root = new TreeNode(val); 6 return root; 7 } 8 if(val<root->val) 9 root->left = f(root->left,val); 10 if(val>root->val) 11 root->right = f(root->right,val); 12 return root; 13 } 14 TreeNode* insertIntoBST(TreeNode* root, int val) { 15 return f(root,val); 16 } 17 };
450. 删除二叉搜索树中的节点 - 力扣(LeetCode) (leetcode-cn.com)
两个思路,一个是根节点保留,找到根节点升序遍历的下一位,赋值给根节点,递归删除根节点的下一位。
还有一个是删除根节点,根节点左子树,接到根节点升序遍历的下一位,的左子树。
1 class Solution { 2 public: 3 TreeNode* deleteNode(TreeNode* root, int key) {//还是分类讨论思路,不要以不空操作,以空判断。 4 if(root==nullptr) 5 return root; 6 if(root->val == key){ 7 if(!root->left&&!root->right) 8 return nullptr; 9 else if(!root->left){//最终递归终止条件 10 root = root->right; 11 }else if(!root->right){ 12 root = root->left; 13 }else{//左右子树都不为空,最复杂,按照中序遍历升序,下面是按照后一位作为root 14 TreeNode* temp = root->right; 15 while(temp->left) 16 temp = temp->left; 17 root->val = temp->val;//赋值根节点后,要删除temp节点,temp节点左为空,右节点可能为空 18 delete temp; 19 } 20 return root; 21 } 22 if(key<root->val) 23 root->left = deleteNode(root->left,key); 24 if(key>root->val) 25 root->right = deleteNode(root->right,key); 26 return root; 27 } 28 };
669. 修剪二叉搜索树 - 力扣(LeetCode) (leetcode-cn.com)
1 class Solution { 2 public: 3 TreeNode* trimBST(TreeNode* root, int low, int high) { 4 if(root==nullptr) 5 return nullptr; 6 if(root->val<low){ 7 root->right = trimBST(root->right,low,high); 8 root = root->right; 9 }else if(root->val>high){ 10 root->left = trimBST(root->left,low,high); 11 root = root->left; 12 }else if(root->val<=high&&root->val>=low){ 13 root->left = trimBST(root->left,low,high); 14 root->right = trimBST(root->right,low,high); 15 } 16 return root; 17 } 18 };
108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode) (leetcode-cn.com)
别人的简洁代码
1 class Solution { 2 public: 3 TreeNode* dfs(vector<int>& nums,int p_left,int p_right) 4 { 5 if(p_left>=p_right)return NULL; 6 int mid = (p_right+p_left)/2; 7 TreeNode *root = new TreeNode(nums[mid]); 8 root->left = dfs(nums,p_left,mid); 9 root->right = dfs(nums,mid+1,p_right); 10 return root; 11 } 12 TreeNode* sortedArrayToBST(vector<int>& nums) { 13 int len = nums.size(); 14 return dfs(nums,0,len); 15 } 16 };
我的
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 * }; 11 */ 12 class Solution { 13 public: 14 TreeNode* f(TreeNode* root,vector<int> nums,int i,int end){//每次取中点作为根。 15 // cout<<i<<end<<endl; 16 if(i>end) 17 return root; 18 if(root == nullptr){ 19 root = new TreeNode(nums[(i+end)/2]); 20 // cout<<"root->val="<<root->val<<endl;; 21 if(i!=end){//剪枝 22 root->left = f(root->left,nums,i,(i+end)/2-1); 23 root->right = f(root->right,nums,(i+end)/2+1,end); 24 } 25 // return root;//为啥子在这加一个return树才能构建,因为二次声明了root,出了bug 26 } 27 else if(nums[(i+end)/2]<root->val)//好像没必要。 28 root->left = f(root->left,nums,i,end); 29 else if(nums[(i+end)/2]>root->val) 30 root->right = f(root->right,nums,i,end); 31 return root; 32 } 33 TreeNode* sortedArrayToBST(vector<int>& nums) { 34 if(nums.size()==0) 35 return nullptr; 36 TreeNode* root = new TreeNode(nums[nums.size()/2]); 37 root->left = f(root->left,nums,0,nums.size()/2-1); 38 root->right = f(root->right,nums,nums.size()/2+1,nums.size()-1); 39 return root; 40 } 41 };