题意
题目描述就不复述了,写的啰嗦就算了还有歧义。
其实就是给你一个有N个节点的二叉树root和有N个值的序列voyage,让你通过对调
k
k
k个节点的左右子树(
k
k
k大于等于0),使得二叉树的前序遍历和所给序列相等,如果无法做到则返回[-1],否则返回交换了左右子树的所有节点的列表。
注意:
- 是交换左右子树,不是交换左节点和右节点的值!!
- 序列的长度也为N,不用考虑序列不等长的问题
- 节点值各不相同
分析
在前序遍历中,如果交换一个节点的左右子树,在那之前遍历到的其他节点包括这个节点的顺序不会发生改变。
因此可以定义全局变量
i
i
i,记录在序列voyage中判断进行到的位置
使用深度优先遍历
- 如果当前节点为空则返回true(表明在 i i i之前的序列匹配均可以通过翻转得到)
- 当前节点不为空,则判断当前节点的值与voyage[i]是否相等若相等则继续遍历,i+1;
- 当前节点值与voyage[i]不相等,那么判断父节点的右子节点的值是否相等,如果相等则交换父节点的左右子树,继续遍历交换后父节点的左子树,并记录经过了翻转的父节点值。
- 以上三种情况都不符合的说明无法通过翻转得到,返回false
C++代码
vector<int> flip;
int i = 0;
bool dfs(TreeNode* currnode, TreeNode* parent, vector<int>& voyage)
{
if(currnode==NULL) return true;
if(currnode->val==voyage[i]){
i++;
if(dfs(currnode->left, currnode, voyage)==false) return false;
if(dfs(currnode->right, currnode, voyage)==false) return false;
}else if(parent->right!=NULL && parent->right->val==voyage[i]){
flip.push_back(parent->val);
parent->left = parent->right; parent->right = currnode;
if(dfs(parent->left, parent, voyage)==false) return false;
}else return false;
return true;
}
vector<int> flipMatchVoyage(TreeNode* root, vector<int>& voyage) {
vector<int> error; error.push_back(-1);
if(root->val!=voyage[i++]) return error;
if(dfs(root->left, root, voyage)==false) return error;
if(dfs(root->right, root, voyage)==false) return error;
return flip;
}
执行用时:4 ms, 在所有 C++ 提交中击败了90.78%的用户
内存消耗:13.2 MB, 在所有 C++ 提交中击败了55.17%的用户