本题我采用了两种方法来做,
方法一,时间复杂度O(N),空间复杂度O(K),K是符合条件的结点的个数,最坏情况是N,最好情况是0
每次遍历一个结点的时候,如果该结点的左子树不为空,则交换左右子树,并且再交换后,左子树不为空,则将交换后左子树的父节点(也就是当前结点)保存到栈当中
如果右子树为空且左子树为空,判断栈内是否还有元素,如果没有,则退出递归,如果有,则取出栈顶树结点的指针,将本次操作结点的右子树赋值为栈顶结点的左子树,并且让栈顶结点的左子树赋值为空,完成后将该栈顶结点出栈
/**
* 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:
stack<TreeNode*> cache_stack;
// 交换结点的左右子树
void swapNode(TreeNode* node){
TreeNode * temp = node->left;
node->left = node->right;
node->right = temp;
}
void orderNode(TreeNode* now){
if(now->left != NULL){
swapNode(now);
if(now->left != NULL)
cache_stack.push(now);
}
else if(now->right == NULL){
if(cache_stack.empty())
return;
now->right = cache_stack.top()->left;
cache_stack.top()->left = NULL;
cache_stack.pop();
}
orderNode(now->right);
}
// 先序遍历折叠到右子树, 无法直接替换掉root,
// 只能在原基础上修改掉 root 的左右子树的分布
void flatten(TreeNode* root) {
if(root == nullptr) return;
orderNode(root);
}
};
方法一,时间复杂度O(N),空间复杂度O(1)
每次将结点的右子树进行先展开处理,然后记录离根节点最近的展开结点,完成右子树后再对左子树进行展开处理,由于此时已经处理了右子树,此时可以将右子树的结点拼接到左子树上。
/**
* 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* best_right = nullptr;
void flatten(TreeNode* root) {
if (root == nullptr) return;
flatten(root->right);
flatten(root->left);
root->right = best_right;
root->left = nullptr;
best_right = root;
}
};