LeetCode-31
1276. 不浪费原料的汉堡制作方案
- 解方程,判断是非负整数解就行
- 用位运算,能快一点
1 | class Solution { |
1185. 一周中的第几天
1 | class Solution { |
2706. 购买两块巧克力
1 | class Solution { |
2735. 收集巧克力
1 | class Solution { |
1599. 经营摩天轮的最大利润
模拟
- 模拟经营
1 | class Solution { |
优化
- 数组遍历结束后,剩下的乘客可以不用模拟,直接/4看有几次就好
- 如果
boardingCost
runningCost
的值恰好无论如何都无法盈利,可以不算后面的
1 | class Solution { |
889. 根据前序和后序遍历构造二叉树
- 对于根节点,先序序列的右侧是左节点,后序序列的右测是右节点
- 如果两个节点不同,则节点有两个子节点,如果相同,则该节点可能是左节点,也可能是右节点
- 对于其他节点,维护好该节点可在先序序列中可查询子代的范围,如果范围是1,则无子代,否则继续插入子代
非递归算法
- 两个数组,分别记录节点在先序、后序序列中的位置
- queue保存当前节点位置,以及在先序序列中后代的范围
1 | class Solution { |
递归算法
1 | class Solution { |
- 递归反而更快了
106. 从中序与后序遍历序列构造二叉树
1 | class Solution { |
105. 从前序与中序遍历序列构造二叉树
1 | class Solution { |
590. N 叉树的后序遍历
1 | /* |
589. N 叉树的前序遍历
1 | class Solution { |
429. N 叉树的层序遍历
1 | /* |
103. 二叉树的锯齿形层序遍历
1 | /** |
1 | class Solution { |
107. 二叉树的层序遍历 II
1 | class Solution { |
102. 二叉树的层序遍历
1 | class Solution { |
987. 二叉树的垂序遍历
- 题目的要求很繁琐,需要输出二维数组,y坐标相同的节点放在同一数组内
- 且需要高层的放在底层的后面,同层的小值位于大值前面
1 | class Solution { |
1 | class Solution { |
145. 二叉树的后序遍历
递归
1 | class Solution { |
非递归
- 在中序遍历的基础上改造
- 对于当前节点,持续向左走压栈,直到无法往左走
- 此时栈顶节点的左子树访问结束,输出栈顶元素
- 若右子树为空,则栈顶元素的右子树访问完成,可以将该元素弹出栈
- 若右子树不为空,考虑该右子树是否是刚才访问过的,通过prev记录上一个输出的节点
- 若prev于当前元素的right相同,则当前节点已经访问过右子树,输出当前节点
- 若prev于当前元素的right不同,则当前节点变成右子树
- 此时栈顶元素的左子树节点访问结束,即重复第二步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode *> s;
TreeNode *cur = root, *prev = nullptr;
while(!s.empty() || cur) {
while(cur) {
s.push(cur);
cur = cur->left;
}
cur = s.top();
if(cur->right && cur->right != prev) {
cur = cur->right;
} else {
prev = cur;
s.pop();
res.push_back(cur->val);
cur = nullptr;
}
}
return res;
}
};
144. 二叉树的前序遍历
递归
1 | class Solution { |
非递归
1 | class Solution { |
94. 二叉树的中序遍历
递归
1 | class Solution { |
非递归
- 对于当前节点,持续向左走压栈,直到无法往左走
- 此时栈顶节点的左子树访问结束
- 将右子树变成当前元素,若右子树为空,则栈顶元素的右子树访问完成,可以将该元素弹出栈
- 此时栈顶元素的左子树节点访问结束,即重复第二步
1 | class Solution { |
236. 二叉树的最近公共祖先
ac
1 | class Solution { |
- 后序遍历时,如果找到目标节点,那么当前栈就是所有祖先
- 对比两个栈,找到最近的祖先
优化
- 减少一次遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54class Solution {
stack<TreeNode*> rev(stack<TreeNode*> s) {
stack<TreeNode*> ans;
while(!s.empty()) {
ans.push(s.top());
s.pop();
}
return ans;
}
void findTreeNode(TreeNode *root, TreeNode *p, TreeNode *q, stack<TreeNode*>& pstack, stack<TreeNode*>& qstack) {
stack<TreeNode *> s;
TreeNode *cur = root, *prev = nullptr;
bool findp = false, findq = false;
while(!s.empty() || cur) {
while(cur) {
s.push(cur);
cur = cur->left;
}
cur = s.top();
if(cur->right && prev != cur->right) {
cur = cur->right;
} else {
prev = cur;
if(cur == p) {
pstack = rev(s);
findp = true;
}
if(cur == q) {
qstack = rev(s);
findq = true;
}
if(findp && findq) break;
s.pop();
cur = nullptr;
}
}
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack<TreeNode *> pstack, qstack;
findTreeNode(root, p, q, pstack, qstack);
TreeNode *ans = nullptr;
while(!pstack.empty() && !qstack.empty()) {
if(pstack.top() == qstack.top()) {
ans = pstack.top();
pstack.pop();
qstack.pop();
} else {
break;
}
}
return ans;
}
};
继续优化
非递归
- 参考的代码是递归的,我改成非递归的
1 | class Solution { |
- 不用引用会快一点
1 | class Solution { |
递归
1 | class Solution { |
- 避免stl会快
993. 二叉树的堂兄弟节点
非递归
1 | class Solution { |
递归
1 | class Solution { |
- leetcode真奇怪,递归算法反而会更快
2641. 二叉树的堂兄弟节点 II
ac
1 | class Solution { |
优化
- 层次遍历
- 计算子节点(下一层节点)的和
- 父节点对子节点修改,改为两兄弟之和
- 获得当前层的和(
prev_level_sum
),将当前节点值(node->val
)改为prev_level_sum
-
node->val
1 | class Solution { |