102(层序遍历)
题目:
这里与邓老师讲的唯一不同之处在于需要判断节点是否在某一层,把同属于某一层的节点一起输出。
思路就是在循环里每次不是pop一次,而是每次把当前队列(插入之前)pop空。
代码
/**
* 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<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>ans;
if (!root) return ans;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()) {
int n = q.size();
vector<int>tmp;
for (int i = 0; i < n; i++) {
cout << q.front()->val << " " ;
tmp.push_back(q.front()->val);
if (q.front()->left)q.push(q.front()->left);
if (q.front()->right)q.push(q.front()->right);
q.pop();
}
cout << endl;
ans.push_back(tmp);
}
return ans;
}
};
103(层序遍历变形)
题目:
其实跟102一模一样,就是用一个flag判断一下是奇数层还是偶数层,reverse一下就好啦
/**
* 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<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>>ans;
if (!root)return ans;
queue<TreeNode*>q;
q.push(root);
int k = 0;
while(!q.empty()) {
int n = q.size();
vector<int>tmp;
for (int i = 0; i < n; i++) {
tmp.push_back(q.front()->val);
if (q.front()->left)q.push(q.front()->left);
if (q.front()->right)q.push(q.front()->right);
q.pop();
}
if (k % 2 == 1) {
reverse(tmp.begin(), tmp.end());
}
k++;
ans.push_back(tmp);
}
return ans;
}
};
105(从前序与中序遍历序列构造二叉树)
题目:
这题就是一个递归,关键在找到递归的位置,也就是四个子数组的开始和结束:
手动分数组版本
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int m = preorder.size();
if(m == 0) return NULL;
TreeNode* root = new TreeNode(preorder[0]);
vector<int> preorder_left, inorder_left, preorder_right, inorder_right;
//在inorder里面寻找根节点,划分左子树和右子树
int i;
//构造左子树的中序遍历
for(i = 0; i < m; i ++){
if(inorder[i] == preorder[0]) break;
inorder_left.push_back(inorder[i]);
}
//构造右子树的中序遍历
for(i = i + 1; i < m; i ++){
inorder_right.push_back(inorder[i]);
}
for(int j = 1; j < m; j ++){
//构造左子树的前序遍历
if(j <= inorder_left.size())
preorder_left.push_back(preorder[j]);
//构造右子树的前序遍历
else preorder_right.push_back(preorder[j]);
}
root->left = buildTree(preorder_left, inorder_left);
root->right = buildTree(preorder_right, inorder_right);
return root;
}
};
哈希表版本
class Solution {
private:
unordered_map<int, int> index;
public:
TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
if (preorder_left > preorder_right) {
return nullptr;
}
// 前序遍历中的第一个节点就是根节点
int preorder_root = preorder_left;
// 在中序遍历中定位根节点
int inorder_root = index[preorder[preorder_root]];
// 先把根节点建立出来
TreeNode* root = new TreeNode(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
// 构造哈希映射,帮助我们快速定位根节点
for (int i = 0; i < n; ++i) {
index[inorder[i]] = i;
}
return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
}
};