树 | ||
递归(2.22) | ||
1. 树的高度 | 第一次可做出Ok |
|
2. 平衡树 | 思考后可做出Ok |
|
3. 两节点的最长路径 | 思考后可做出 |
|
4. 翻转树 | 修改后可做出 |
|
5. 归并两棵树 | 第一次可做出Ok |
|
6. 判断路径和是否等于一个数 | 修改后可做出 |
|
7. 统计路径和等于一个数的路径数量 | 第一次未做出 | ※ |
8. 子树 | 修改后可做出 |
|
9. 树的对称 | 第一次可做出Ok |
|
10. 最小路径 | 修改后可做出Ok |
|
11. 统计左叶子节点的和 | 第一次可做出, 解法可简化 | ※ |
12. 相同节点值的最大路径长度 | 思考后可做出 | ※ |
13. 间隔遍历 | 第一次可做出Ok |
|
14. 找出二叉树中第二小的节点 | 思考后可做出, 解法可简化 | ※ |
层次遍历 | ||
1. 一棵树每层节点的平均数 | 第一次可做出Ok |
|
2. 得到左下角的节点 | 思考后可做出, 解法可简化 | ※ |
前中后序遍历 | ||
1. 非递归实现二叉树的前序遍历 | 修改后可做出 | ※ |
2. 非递归实现二叉树的后序遍历 | 思考后可做出Ok |
|
3. 非递归实现二叉树的中序遍历 | 第一次未做出 | ※ |
BST | ||
1. 修剪二叉查找树 | 第一次可做出Ok |
|
2. 寻找二叉查找树的第 k 个元素 | 思考后可做出, 解法可简化 | ※ |
3. 把二叉查找树每个节点的值都加上比它大的节点的值 | 第一次可做出Ok |
|
4. 二叉查找树的最近公共祖先 | 第一次可做出Ok |
|
5. 二叉树的最近公共祖先 | 思考后可做出, 解法可简化 | ※ |
6. 从有序数组中构造二叉查找树(2.23) | 第一次可做出Ok |
|
7. 根据有序链表构造平衡的二叉查找树 | 思考后可做出,同上 |
|
8. 在二叉查找树中寻找两个节点,使它们的和为一个给定值 | 解法可简化 | ※ |
9. 在二叉查找树中查找两个节点之差的最小绝对值 | 思考后可做出, 解法可简化 | ※ |
10. 寻找二叉查找树中出现次数最多的值 | 思考后可做出 |
|
Trie | ||
1. 实现一个 Trie | 第一次未做出 | ※ |
2. 实现一个 Trie,用来求前缀和 | 思考后可做出,类上 |
|
递归
一棵树要么是空树,要么有两个指针,每个指针指向一棵树。树是一种递归结构,很多树的问题可以使用递归来处理。
1. 树的高度
104. Maximum Depth of Binary Tree (Easy)
https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
2. 平衡树
110. Balanced Binary Tree (Easy)
https://leetcode-cn.com/problems/balanced-binary-tree/
3. 两节点的最长路径
543. Diameter of Binary Tree (Easy)
https://leetcode-cn.com/problems/diameter-of-binary-tree/
4. 翻转树
226. Invert Binary Tree (Easy)
https://leetcode-cn.com/problems/invert-binary-tree/
5. 归并两棵树
617. Merge Two Binary Trees (Easy)
https://leetcode-cn.com/problems/merge-two-binary-trees/
6. 判断路径和是否等于一个数
112. Path Sum (Easy)
https://leetcode-cn.com/problems/path-sum/
7. 统计路径和等于一个数的路径数量
437. Path Sum III (Easy)
https://leetcode-cn.com/problems/path-sum-iii/
/**
* 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 pathStartFrom(TreeNode* root, int sum){
if(root==NULL) return 0;
int cur=sum-root->val;
return pathStartFrom(root->left,cur)+pathStartFrom(root->right,cur)+((cur==0)?1:0);
}
int pathSum(TreeNode* root, int sum) {
if(root==NULL) return 0;
return pathStartFrom(root,sum)+pathSum(root->left,sum)+pathSum(root->right,sum);
}
};
8. 子树
572. Subtree of Another Tree (Easy)
https://leetcode-cn.com/problems/subtree-of-another-tree/
9. 树的对称
101. Symmetric Tree (Easy)
https://leetcode-cn.com/problems/symmetric-tree/
10. 最小路径
111. Minimum Depth of Binary Tree (Easy)
https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/
11. 统计左叶子节点的和
404. Sum of Left Leaves (Easy)
https://leetcode-cn.com/problems/sum-of-left-leaves/
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 sumOfLeftLeaves(root->right)+root->left->val;
else
return sumOfLeftLeaves(root->right)+sumOfLeftLeaves(root->left);
}
};
12. 相同节点值的最大路径长度
687. Longest Univalue Path (Easy)
https://leetcode-cn.com/problems/longest-univalue-path/
class Solution {
public:
int longestPathFromRoot(TreeNode* root,int val){
if(root==NULL||root->val!=val) return 0;
return 1+max(longestPathFromRoot(root->left,val),longestPathFromRoot(root->right,val));
}
int longestUnivaluePath(TreeNode* root) {
if(root==NULL) return 0;
int fr=longestPathFromRoot(root->left,root->val)+longestPathFromRoot(root->right,root->val);
return max(fr,max(longestUnivaluePath(root->left),longestUnivaluePath(root->right)));
}
};
13. 间隔遍历
337. House Robber III (Medium)
https://leetcode-cn.com/problems/house-robber-iii/
14. 找出二叉树中第二小的节点
671. Second Minimum Node In a Binary Tree (Easy)
https://leetcode-cn.com/problems/second-minimum-node-in-a-binary-tree/
class Solution {
public:
int findSecondMinimumValue(TreeNode* root) {
if(root==NULL||root->left==NULL) return -1;
int l=(root->left->val==root->val)?findSecondMinimumValue(root->left):root->left->val;
int r=(root->right->val==root->val)?findSecondMinimumValue(root->right):root->right->val;
if(l!=-1&&r!=-1) return min(l,r);
return (l==-1)?r:l;
}
};
层次遍历
使用 BFS 进行层次遍历。不需要使用两个队列来分别存储当前层的节点和下一层的节点,因为在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历这么多节点数,就能保证这次遍历的都是当前层的节点。
1. 一棵树每层节点的平均数
637. Average of Levels in Binary Tree (Easy)
https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/
2. 得到左下角的节点
513. Find Bottom Left Tree Value (Easy)
https://leetcode-cn.com/problems/find-bottom-left-tree-value/
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> q;
if(root==NULL) return 0;
q.push(root);
while(!q.empty()){
root=q.front();
q.pop();
if(root->right!=NULL) q.push(root->right); //先右后左
if(root->left!=NULL) q.push(root->left);
}
return root->val;
}
};
前中后序遍历
层次遍历使用 BFS 实现,利用的就是 BFS 一层一层遍历的特性;而前序、中序、后序遍历利用了 DFS 实现。
前序、中序、后序遍只是在对节点访问的顺序有一点不同,其它都相同。
① 前序
void dfs(TreeNode root) {
visit(root);
dfs(root.left);
dfs(root.right);
}
② 中序
void dfs(TreeNode root) {
dfs(root.left);
visit(root);
dfs(root.right);
}
③ 后序
void dfs(TreeNode root) {
dfs(root.left);
dfs(root.right);
visit(root);
}
1. 非递归实现二叉树的前序遍历
144. Binary Tree Preorder Traversal (Medium)
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
1. 非递归
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if(root==NULL) return res;
stack<TreeNode*> st;
st.push(root);
while(!st.empty()){
root=st.top();
st.pop();
res.push_back(root->val);
if(root->right!=NULL) st.push(root->right); //先右后左,保证左子树先遍历
if(root->left!=NULL) st.push(root->left);
}
return res;
}
};
2. 递归
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res,l,r;
if(root==NULL) return res;
res.push_back(root->val);
l=preorderTraversal(root->left);
r=preorderTraversal(root->right);
for(auto i:l) res.push_back(i);
for(auto i:r) res.push_back(i);
return res;
}
};
2. 非递归实现二叉树的后序遍历
145. Binary Tree Postorder Traversal (Medium)
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
3. 非递归实现二叉树的中序遍历
94. Binary Tree Inorder Traversal (Medium)
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
1. 非递归
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
while(root!=NULL||!st.empty()){
while(root!=NULL){
st.push(root);
root=root->left;
}
TreeNode *cur=st.top();
st.pop();
res.push_back(cur->val);
root=cur->right;
}
return res;
}
};
2. 递归
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> l,r;
if(root==NULL) return l;
l=inorderTraversal(root->left);
l.push_back(root->val);
r=inorderTraversal(root->right);
for(int i:r) l.push_back(i);
return l;
}
};
BST
二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点。
二叉查找树中序遍历有序。
1. 修剪二叉查找树
669. Trim a Binary Search Tree (Easy)
https://leetcode-cn.com/problems/trim-a-binary-search-tree/
2. 寻找二叉查找树的第 k 个元素
230. Kth Smallest Element in a BST (Medium)
https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/
可采用中序遍历
1. 递归
class Solution {
public:
void inOrder(TreeNode* root,int& k,int& val){
if(root==NULL) return;
inOrder(root->left,k,val);
k--;
if(k==0) val=root->val;
inOrder(root->right,k,val);
}
int kthSmallest(TreeNode* root, int k) {
int res=0;
inOrder(root,k,res);
return res;
}
};
2. 非递归
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> st;
while(root!=NULL||!st.empty()){
while(root!=NULL){
st.push(root);
root=root->left;
}
TreeNode* cur=st.top();
if(k==1) return cur->val;
k--;
st.pop();
root=cur->right;
}
return 0;
}
};
3. 递归解法二
class Solution {
public:
int NumOfElem(TreeNode* root){
if(root==NULL) return 0;
return 1+NumOfElem(root->left)+NumOfElem(root->right);
}
int kthSmallest(TreeNode* root, int k) {
int l=NumOfElem(root->left);
if(l==k-1) return root->val;
else if(l<k-1) return kthSmallest(root->right,k-l-1);
else return kthSmallest(root->left,k);
}
};
3. 把二叉查找树每个节点的值都加上比它大的节点的值
538. Convert BST to Greater Tree (Easy)
https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
4. 二叉查找树的最近公共祖先
235. Lowest Common Ancestor of a Binary Search Tree (Easy)
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
5. 二叉树的最近公共祖先
236. Lowest Common Ancestor of a Binary Tree (Medium)
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==NULL||root==p||root==q) return root;
TreeNode* l=lowestCommonAncestor(root->left,p,q);
TreeNode* r=lowestCommonAncestor(root->right,p,q);
if(l==NULL) return r;
if(r==NULL) return l;
return root;
}
};
6. 从有序数组中构造二叉查找树
108. Convert Sorted Array to Binary Search Tree (Easy)
https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/
7. 根据有序链表构造平衡的二叉查找树
109. Convert Sorted List to Binary Search Tree (Medium)
https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/
8. 在二叉查找树中寻找两个节点,使它们的和为一个给定值
653. Two Sum IV - Input is a BST (Easy)
https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/
1. 中序遍历
class Solution {
public:
void inOrder(TreeNode* root,vector<int>& ret){
if(root==NULL) return;
inOrder(root->left,ret);
ret.push_back(root->val);
inOrder(root->right,ret);
}
bool findTarget(TreeNode* root, int k) {
vector<int> ret;
inOrder(root,ret);
int left=0,right=ret.size()-1;
while(left<right){
if(ret[left]+ret[right]==k) return true;
else if(ret[left]+ret[right]>k) right--;
else left++;
}
return false;
}
};
2. 多个递归(不推荐)
class Solution {
public:
bool findSumFromTwoT(TreeNode* l,TreeNode* r,int k){
if(l==NULL||r==NULL) return false;
if(l->val+r->val==k) return true;
else if(l->val+r->val>k) return findSumFromTwoT(l->left,r,k)||findSumFromTwoT(l,r->left,k);
else return findSumFromTwoT(l->right,r,k)||findSumFromTwoT(l,r->right,k);
}
bool findExistK(TreeNode* root,int k){
if(root==NULL) return false;
if(root->val==k) return true;
else if(root->val<k) return findExistK(root->right,k);
else return findExistK(root->left,k);
}
bool findTarget(TreeNode* root, int k) {
if(root==NULL) return false;
int val=k-root->val;
if(val<=root->val&&findExistK(root->left,val)) return true;
if(val>root->val&&findExistK(root->right,val)) return true;
return findSumFromTwoT(root->left,root->right,k)||findTarget(root->left,k)||findTarget(root->right,k);
}
};
9. 在二叉查找树中查找两个节点之差的最小绝对值
530. Minimum Absolute Difference in BST (Easy)
https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst/
1. 中序求出序列,再求最小差值
2. 直接中序遍历求最小差值
class Solution {
public:
void inOrder(TreeNode* root,TreeNode* &pre,int& ret){
if(root==NULL) return;
inOrder(root->left,pre,ret);
if(pre!=NULL) ret=min(ret,root->val-pre->val);
pre=root;
inOrder(root->right,pre,ret);
}
int getMinimumDifference(TreeNode* root) {
int ret=INT_MAX;
TreeNode* pre=NULL;
inOrder(root,pre,ret);
return ret;
}
};
10. 寻找二叉查找树中出现次数最多的值
501. Find Mode in Binary Search Tree (Easy)
https://leetcode-cn.com/problems/find-mode-in-binary-search-tree/
Trie
Trie,又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种字符串前缀。
1. 实现一个 Trie
208. Implement Trie (Prefix Tree) (Medium)
https://leetcode-cn.com/problems/implement-trie-prefix-tree/
class Trie {
private:
bool isEnd;
Trie* next[26];
public:
/** Initialize your data structure here. */
Trie() {
isEnd=false;
memset(next,0,sizeof(next));
}
/** Inserts a word into the trie. */
void insert(string word) {
Trie* node=this;
for(auto c:word){
if(node->next[c-'a']==NULL)
node->next[c-'a']=new Trie();
node=node->next[c-'a'];
}
node->isEnd=true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
Trie* node=this;
for(auto c:word){
if(node->next[c-'a']==NULL) return false;
node=node->next[c-'a'];
}
return node->isEnd;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
Trie* node=this;
for(auto c:prefix){
if(node->next[c-'a']==NULL) return false;
node=node->next[c-'a'];
}
return true;
}
};
/**
* 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);
*/
2. 实现一个 Trie,用来求前缀和
677. Map Sum Pairs (Medium)