class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 求二叉树的右视图
* @param preOrder int整型vector 先序遍历
* @param inOrder int整型vector 中序遍历
* @return int整型vector
*/
vector<int> res;
struct node{
node* left=nullptr;
node* right=nullptr;
int val=0;
node(int _val):val(_val){}
node(int _val, node* _left, node* _right):left(_left),right(_right),val(_val){}
};
//先序遍历得到根节点,然后在中序遍历中找到根节点、左子树、右子树,返回一层中最右的子树的根节点
vector<int> solve(vector<int>& preOrder, vector<int>& inOrder) {
if(preOrder.empty())return {};
node* root = rebuild(preOrder, inOrder, 0, preOrder.size()-1, 0, inOrder.size()-1);
queue<node*> q;
q.push(root);
int size = 1;
while(!q.empty()){
res.push_back(q.front()->val); //放下一层右边第一个节点
int new_size = 0;
while(size > 0){ //排出当前层,放入下一层
node* temp = q.front();q.pop();
if(temp->right != nullptr){
q.push(temp->right);
new_size++;
} //非空的放入
if(temp->left != nullptr){
q.push(temp->left);
new_size++;
}
--size;
}
size = new_size;
}
return res;
}
//重建二叉树,前序遍历数组的头一个是根节点,在中序遍历中找到根节点,通过下标计算出左右子树的大小,然后确定前序遍历数组中的左子树和右子树的范围,递归得对子树划分;
node* rebuild(vector<int>& preOrder, vector<int>& inOrder, int pre_front_idx, int pre_back_idx, int in_front_idx, int in_back_idx){
if(pre_front_idx > pre_back_idx){
return nullptr;
}
if(pre_front_idx == pre_back_idx){
return new node(preOrder[pre_back_idx]);
}
auto it = find(inOrder.begin()+in_front_idx, inOrder.begin()+in_back_idx, preOrder[pre_front_idx]);
//string有find方法找到下标:s.find(num); vector没有。只有函数,返回迭代器;
int root_idx = distance(inOrder.begin(), it); //找到下标
int left_sz = root_idx - in_front_idx; //左子树有多少个
int right_sz = in_back_idx - root_idx; //右子树有多少个
node* left_node = rebuild(preOrder, inOrder, pre_front_idx+1, pre_front_idx +left_sz , in_front_idx, root_idx-1);
node* right_node = rebuild(preOrder, inOrder, pre_back_idx-right_sz+1, pre_back_idx, root_idx+1, in_back_idx);
return new node(*it, left_node, right_node);
}
};