算法复习:二叉树专题
一、平衡二叉树
leetcode 110. 平衡二叉树
二叉树判断是否平衡。 对逐个结点判断左右子树是否满足条件。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int find_leaves(TreeNode* root,int floor,int max) { if(root==NULL) return max; if(root->left==NULL&&root->right==NULL) { if(max<floor) max=floor; return max; } floor++; max=find_leaves(root->left,floor,max); max=find_leaves(root->right,floor,max); floor--; return max; } bool isBalanced(TreeNode* root) { if(root==NULL) return true; int left=find_leaves(root->left,0,0); if(root->left==NULL) left=-1; int right=find_leaves(root->right,0,0); if(root->right==NULL) right=-1; if(abs(left-right)>1) return false; bool a,b; a=isBalanced(root->left); b=isBalanced(root->right); if(root->left==NULL&&root->right==NULL) return true; return (a&&b); } };
二、二叉树层次遍历
leetcode 513. 找树左下角的值
层次遍历记录queue每次的队头
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: queue<TreeNode*>donser; int findBottomLeftValue(TreeNode* root) { TreeNode* node; donser.push(root); int first=0; while(true) { int size=donser.size(); if(size==0) break; for(int i=0;i<size;i++) { node=donser.front(); if(i==0) first=node->val; donser.pop(); if(node->left!=NULL) donser.push(node->left); if(node->right!=NULL) donser.push(node->right); } } return first; } };
三、二叉树先序遍历
leetcode 114. 二叉树展开为链表
实质上就是先序遍历,把每一个输出的节点存起来,最后连接起来就可以,不需要考虑链接规律。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<TreeNode*> donser; void loop(TreeNode* root) { if(root==NULL) return; donser.push_back(root); loop(root->left); loop(root->right); return; } void flatten(TreeNode* root) //先序遍历 { loop(root); if(donser.size()<=1) return; TreeNode* node; node=root; for(int i=1;i<donser.size();i++) { TreeNode* now; now=donser[i]; node->left=NULL; node->right=now; node=now; } donser.clear(); return; } };
考虑不用辅助数组,就地转换。 node的右节点接在node的左节点的后面,再把node的左节点转移到右边,左边置null
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: void loop(TreeNode* root) { if(root==nullptr) return ; loop(root->left); loop(root->right); if(root->left!=nullptr) { TreeNode* tmp=root->left; while(tmp->right!=nullptr) tmp=tmp->right; tmp->right=root->right; } else root->left=root->right; root->right=root->left; root->left=nullptr; return ; } void flatten(TreeNode* root) { TreeNode * tmp; TreeNode * tmp2; if(root==nullptr) return ; tmp=root->left; tmp2=root->right; loop(tmp); loop(tmp2); root->left=nullptr; root->right=tmp; if(tmp==nullptr) { root->right=tmp2; return; } while(tmp->right!=nullptr) tmp=tmp->right; tmp->right=tmp2; } };
四、二叉树中序遍历
leetcode 230. 二叉搜索树中第K小的元素
对二叉搜索树来说,找第几小就是找中序遍历的第几个节点
方法一:用辅助数组存节点值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> donser; void loop(TreeNode* root,int k) { if(root->left!=NULL) loop(root->left,k); donser.push_back(root->val); if(root->right!=NULL) loop(root->right,k); return; } int kthSmallest(TreeNode* root, int k) { loop(root,k); return donser[k-1]; } };
方法二:不用辅助数组,用两个全局变量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int num=0,res=0; void loop(TreeNode* root,int k) { if(root==NULL) return; loop(root->left,k); num++; if(num==k) { res=root->val; return; } loop(root->right,k); } int kthSmallest(TreeNode* root, int k) { loop(root,k); return res; } };/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int num=0,res=0; void loop(TreeNode* root,int k) { if(root==NULL) return; loop(root->left,k); num++; if(num==k) { res=root->val; return; } loop(root->right,k); } int kthSmallest(TreeNode* root, int k) { loop(root,k); return res; } };
leetcode 94. 二叉树的中序遍历
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> donser; void loop(TreeNode* root) { if(root->left!=NULL) loop(root->left); donser.push_back(root->val); if(root->right!=NULL) loop(root->right); return; } vector<int> inorderTraversal(TreeNode* root) { if(root==NULL) return donser; loop(root); return donser; } };
五、二叉树序列化
leetcode 297. 二叉树的序列化与反序列化 or 面试题37. 序列化二叉树
将string形式的树存储转化为Node形式,将Node形式转化为string形式,思想不难,实现起来有点复杂,涉及到string的处理,层序还原为树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Codec { public: // Encodes a tree to a single string. string serialize(TreeNode* root) { queue<TreeNode*>donser; if(root==NULL) return "[]"; donser.push(root); string outter="["; while(true) { int size=donser.size(); if(size==0) break; for(int i=0;i<size;i++) { TreeNode* node; node=donser.front(); donser.pop(); if(node==NULL) { outter=outter.insert(outter.size(),"null,"); continue; } else { outter=outter.insert(outter.size(),to_string(node->val)+","); } donser.push(node->left); donser.push(node->right); } } outter[outter.size()-1]=']'; while(outter[outter.size()-2]=='l') { outter.erase(outter.size()-6,5); } return outter; } TreeNode* make_node(queue<TreeNode*>donser) { if(!donser.size()) return NULL; queue<TreeNode*>tmp; TreeNode* root=donser.front(); TreeNode* node=root; tmp.push(donser.front()); donser.pop(); int lable=0; while(true) { int size=tmp.size(); if(size==0) break; while(size--) { node=tmp.front(); tmp.pop(); if(node==NULL) continue; if(!donser.size()) { lable=1; break; } node->left=donser.front(); tmp.push(donser.front()); donser.pop(); if(!donser.size()) { lable=1; break; } node->right=donser.front(); tmp.push(donser.front()); donser.pop(); } if(lable) break; } return root; } // Decodes your encoded data to tree. TreeNode* deserialize(string data) { if(data=="[]") return NULL; data.erase(0,1); queue<TreeNode*>donser; while(data!="") { int num=0,lable=-1,lb=0; for(int i=0;;i++) { if(data[0]=='n') { lable=-1; break; } if(data[i]=='-') { lb=-2; continue; } if(data[i]==','||data[i]==']') { lable=i; break; } num*=10; num+=data[i]-'0'; } if(lable==-1) { data.erase(0,5); donser.push(NULL); } else { if(lb==-2) { num*=-1; lb=0; } data.erase(0,lable+1); TreeNode* node=new TreeNode(num); donser.push(node); } } TreeNode* root=donser.front(); root=make_node(donser); return root; } }; // Your Codec object will be instantiated and called as such: // Codec codec; // codec.deserialize(codec.serialize(root));
六、由前序中序确定一颗二叉树
leetcode 105. 从前序与中序遍历序列构造二叉树
由两个序列划分左右子树,递归条件构建
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int str=0; TreeNode* loop(vector<int>& preorder,vector<int>& inorder) { vector<int>in_left,in_right;//先找中序的左右部分 int lable=0; for(int i=0;i<inorder.size();i++) { if(inorder[i]==preorder[str]) { lable=1; continue; } if(lable==0) in_left.push_back(inorder[i]); if(lable==1) in_right.push_back(inorder[i]); } TreeNode* node=new TreeNode(preorder[str]); if(in_left.size()) { str++; node->left=loop(preorder,in_left); } if(in_right.size()) { str++; node->right=loop(preorder,in_right); } return node; } TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if(preorder.size()==0) return NULL; TreeNode* root; root=loop(preorder,inorder); return root; } };
七、字典树—前缀树
leetcode 208. 实现 Trie (前缀树)
属于多叉树,重点关注这个,字节面试问过很多次
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
struct TrieNode { TrieNode *next[26]; bool is_end; }; class Trie { public: /** Initialize your data structure here. */ Trie() {} struct TrieNode * root=new TrieNode(); void insert(string word) { struct TrieNode * node=root; for(int i=0;i<word.size();i++) { if(node->next[word[i]-'a']==NULL) { struct TrieNode * new_node=new TrieNode(); node->next[word[i]-'a']=new_node; } node=node->next[word[i]-'a']; } node->is_end=true; } bool search(string word) { struct TrieNode * node=root; for(int i=0;i<word.size();i++) { if(node!=NULL) { node=node->next[word[i]-'a']; } } if(node!=NULL&&node->is_end==true) return true; return false; } bool startsWith(string prefix) { struct TrieNode * node=root; for(int i=0;i<prefix.size();i++) { if(node!=NULL) { node=node->next[prefix[i]-'a']; } } if(node!=NULL) return true; return false; } }; /** * Your Trie object will be instantiated and called as such: * Trie* obj = new Trie(); * obj->insert(word); * bool param_2 = obj->search(word); * bool param_3 = obj->startsWith(prefix); */