算法高频题
-
刷题:LeetCode(Top 100-150题,至少刷两遍)。重点:链表、树、二分查找、动态规划、回溯、栈/队列。
-
每一个题型,前10个高频题
算法思考框架参考:算法题思维框架-CSDN博客
高频顺序参考网站:CodeTop 面试题目总结
1.树
1.1102. 二叉树的层序遍历 - 力扣(LeetCode)
https://leetcode.cn/problems/binary-tree-level-order-traversal/
思考:题目已经给出层序遍历,按照思考框架。
BFS:
vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> ans;queue<TreeNode*> q;q.push(root);while(!q.empty()){int levelSize = q.size();vector<int> layer;for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();// process node->vallayer.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}// current layer is overans.push_back(layer);}return ans;}
DFS:需要记录深度depth,回溯时根据depth添加到对应数组里。
class Solution {
public:vector<vector<int>> ans;void dfs(TreeNode* root,int depth){if(!root) return;if(depth>=ans.size()){ans.push_back({root->val});}else{ans[depth].push_back(root->val);}dfs(root->left,depth+1);dfs(root->right,depth+1);}vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};dfs(root,0);return ans;}
};
1.2236. 二叉树的最近公共祖先 - 力扣(LeetCode)
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
思考:按照思维框架,我们可以看出先需要知道左右子树,显然是后续遍历。
具体思路:
- 如果当前节点为nullptr,返回nullptr。
- 如果当前节点就是p或q,那么返回当前节点。
- 递归遍历左子树和右子树,得到左右子树的结果。
- 如果左子树和右子树的结果都不为空,说明当前节点就是p和q的最近公共祖先。
- 如果左子树结果不为空,右子树结果为空,说明p和q都在左子树中,返回左子树的结果。
- 如果右子树结果不为空,左子树结果为空,说明p和q都在右子树中,返回右子树的结果。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == nullptr || root == p || root == q){return root;}TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left!=nullptr && right!=nullptr){return root;}return left!=nullptr?left:right;}
时间复杂度:O(N),最坏情况下,我们需要访问所有节点。
空间复杂度:O(H),递归调用的栈深度取决于二叉树的高度,最坏情况下(树退化为链表)为 O(N),平均情况下为 O(logN)。
1.3103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)
https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/description/
这道题BFS的变种,核心思路仍然仍按层遍历,但需要根据层数的奇偶性来决定遍历方向:
-
使用队列进行BFS:标准的层序遍历方法
-
使用标志位记录方向:用一个布尔值
leftToRight
记录当前层应该是从左到右还是从右到左 -
根据方向处理每层结果:
-
如果是左到右:直接按遍历顺序加入结果
-
如果是右到左:将当前层的结果反转后加入结果
-
方法一:标准BFS + 反转
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> res;queue<TreeNode*> q;q.push(root);bool leftToRight = true;while(!q.empty()){int levelSize = q.size();vector<int> layer(levelSize);for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();int index = leftToRight?i:levelSize-1-i;layer[index] = node->val;if(node->left) q.push(node->left);if(node->right) q.push(node->right);}res.push_back(layer);leftToRight = !leftToRight;}return res;}
-
时间复杂度:O(n)
-
空间复杂度:O(n)
方法二:使用双端队列(Deque)
//TODO:keep learning.