CONTENTS
LeetCode 106. 从中序与后序遍历序列构造二叉树(中等)
【题目描述】
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历,postorder
是同一棵树的后序遍历,请你构造并返回这颗二叉树 。
【示例 1】
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
【示例 2】
输入:inorder = [-1], postorder = [-1]
输出:[-1]
【提示】
1
<
=
i
n
o
r
d
e
r
.
l
e
n
g
t
h
<
=
3000
1 <= inorder.length <= 3000
1<=inorder.length<=3000
p
o
s
t
o
r
d
e
r
.
l
e
n
g
t
h
=
=
i
n
o
r
d
e
r
.
l
e
n
g
t
h
postorder.length == inorder.length
postorder.length==inorder.length
−
3000
<
=
i
n
o
r
d
e
r
[
i
]
,
p
o
s
t
o
r
d
e
r
[
i
]
<
=
3000
-3000 <= inorder[i], postorder[i] <= 3000
−3000<=inorder[i],postorder[i]<=3000
inorder
和 postorder
都由不同的值组成
postorder
中每一个值都在 inorder
中
inorder
保证是树的中序遍历
postorder
保证是树的后序遍历
【分析】
与 LeetCode 105. 类似,唯一区别就是要通过后序遍历的最后一个节点来确定根节点。
【代码】
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
}
TreeNode* build(vector<int>& in, int inSt, int inEd, vector<int>& pos, int posSt, int posEd) {
if (posSt > posEd) return nullptr;
TreeNode* root = new TreeNode(pos[posEd]); // 根节点就是后序遍历的最后一个节点
int k = 0;
while (in[k] != pos[posEd]) k++; // 在中序遍历中找到根节点
int leftChildNum = k - inSt; // 左子树节点数
root->left = build(in, inSt, k - 1, pos, posSt, posSt + leftChildNum - 1);
root->right = build(in, k + 1, inEd, pos, posSt + leftChildNum, posEd - 1);
return root;
}
};
LeetCode 107. 二叉树的层序遍历 II(中等)
【题目描述】
给你二叉树的根节点 root
,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
【示例 1】
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]
【示例 2】
输入:root = [1]
输出:[[1]]
【示例 3】
输入:root = []
输出:[]
【提示】
树中节点数目在范围
[
0
,
2000
]
[0, 2000]
[0,2000] 内
−
1000
<
=
N
o
d
e
.
v
a
l
<
=
1000
-1000 <= Node.val <= 1000
−1000<=Node.val<=1000
【分析】
与 LeetCode 102. 类似,只需要最后将答案翻转一下即可。
【代码】
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> Q;
if (root) Q.push(root);
while (!Q.empty()) {
vector<int> v;
int cnt = Q.size();
while (cnt--) {
TreeNode* t = Q.front();
Q.pop();
v.push_back(t->val);
if (t->left) Q.push(t->left);
if (t->right) Q.push(t->right);
}
res.push_back(v);
}
reverse(res.begin(), res.end());
return res;
}
};
LeetCode 108. 将有序数组转换为二叉搜索树(简单)
【题目描述】
给你一个整数数组 nums
,其中元素已经按升序排列,请你将其转换为一棵平衡二叉搜索树(平衡二叉树是指该树所有节点的左右子树的高度相差不超过 1)。
【示例 1】
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案
【示例 2】
输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。
【提示】
1
<
=
n
u
m
s
.
l
e
n
g
t
h
<
=
1
0
4
1 <= nums.length <= 10^4
1<=nums.length<=104
−
1
0
4
<
=
n
u
m
s
[
i
]
<
=
1
0
4
-10^4 <= nums[i] <= 10^4
−104<=nums[i]<=104
nums
按严格递增顺序排列
【分析】
为了保持平衡,每个子树的根节点都应该是节点序列的中点,然后可以递归地通过左半部分区间与右半部分区间递归地创建平衡树。
【代码】
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return build(nums, 0, nums.size() - 1);
}
TreeNode* build(vector<int>& nums, int l, int r) {
if (l > r) return nullptr;
int mid = l + r >> 1;
TreeNode* root = new TreeNode(nums[mid]);
root->left = build(nums, l, mid - 1);
root->right = build(nums, mid + 1, r);
return root;
}
};
LeetCode 109. 将有序数组转换为二叉搜索树(中等)
【题目描述】
给定一个单链表的头节点 head
,其中的元素按升序排序,将其转换为平衡二叉搜索树。
【示例 1】
输入: head = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高度平衡的二叉搜索树。
【示例 2】
输入: head = []
输出: []
【提示】
head
中的节点数在
[
0
,
2
∗
1
0
4
]
[0, 2 * 10^4]
[0,2∗104] 范围内
−
1
0
5
<
=
N
o
d
e
.
v
a
l
<
=
1
0
5
-10^5 <= Node.val <= 10^5
−105<=Node.val<=105
【分析】
与上一题的区别就在于链表取中点的时候不能随机访问,在链表里面取中点的时间复杂度是 O ( n ) O(n) O(n) 的,如果用额外 O ( n ) O(n) O(n) 的空间开一个数组,那就和上一题一样。
如果对于每一段链表都用遍历的方式找中点,第一层所需的时间为 n / 2 n / 2 n/2,第二层为 2 ∗ n / 4 = n / 2 2 * n / 4 = n / 2 2∗n/4=n/2,以此类推一共有 l o g n log n logn 层,因此时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn)。
注意如果对于每一段区间都遍历一次求出总长度那么时间复杂度应该是 O ( n 2 ) O(n^2) O(n2),可以在函数中传入区间左右端点从而避免每次都遍历整段区间。
【代码】
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
int n = 0;
for (auto p = head; p; p = p->next) n++;
return build(head, 0, n - 1);
}
// head 为当前区间的表头,l 为区间左端点下标,r 为区间右端点下标
TreeNode* build(ListNode* head, int l, int r) {
if (l > r) return nullptr;
int mid = l + r >> 1; // 中间节点的下标
ListNode* p = head;
for (int i = 0; i < mid - l; i++) p = p->next; // 中间节点需要从位置 l 向右遍历 mid - l 次
TreeNode* root = new TreeNode(p->val);
root->left = build(head, l, mid - 1);
root->right = build(p->next, mid + 1, r);
return root;
}
};
LeetCode 110. 平衡二叉树(简单)
【题目描述】
给定一个二叉树,判断它是否是平衡二叉树。
【示例 1】
输入:root = [3,9,20,null,null,15,7]
输出:true
【示例 2】
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
【示例 3】
输入:root = []
输出:true
【提示】
head
中的节点数在
[
0
,
2
∗
1
0
4
]
[0, 2 * 10^4]
[0,2∗104] 范围内
−
1
0
5
<
=
N
o
d
e
.
v
a
l
<
=
1
0
5
-10^5 <= Node.val <= 10^5
−105<=Node.val<=105
【分析】
只要判断每个子树的根节点左右子树的高度差是否都满足小于等于 1 即可,求解最大高度的方法就是 LeetCode 104.。
注意不能只判断根节点的左右子树高度,例如下面这棵树就不是平衡的,但是根节点左右子树高度都是 3:
【代码】
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool res = true;
bool isBalanced(TreeNode* root) {
getHeight(root);
return res;
}
int getHeight(TreeNode* root) {
if (!root) return 0;
int left = getHeight(root->left), right = getHeight(root->right);
if (abs(left - right) > 1) res = false; // 存在一个子树的根节点其左右子树高度差大于一
return max(left, right) + 1;
}
};