LeetCode HOT100 - 二叉树展开为链表
首先,因为是树,所以肯定是自顶向下的
接着,因为本质还是做前序遍历,所以肯定还是要 dfs
核心就是每次左子树的尾节点要接到右子树的根节点,并且把该节点的左子树置空,右节点接到原来的左子树的根节点上
然后传回这条链的末尾节点
所以逻辑上做些处理
/**
* 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:
void flatten(TreeNode* root) {
auto dfs = [&](this auto&& self, TreeNode* u) -> TreeNode* {
if (!u) {
return u;
}
if ((!u->left) && (!u->right)) {
return u;
}
auto x = self(u->left);
auto y = self(u->right);
if (x && u->right) x->right = u->right;
if (u->left) u->right = u->left;
u->left = nullptr;
if (y) {
return y;
}
return x;
};
dfs(root);
}
};
不过这样做的话空间复杂度大致是 O(h),如果要做到严格 O(1) 的话还是要做些优化和思路上的调整
一般就是要迭代原地调整指针
这里就直接先放代码了
class Solution {
public:
void flatten(TreeNode* root) {
TreeNode* cur = root;
while (cur) {
if (cur->left) {
TreeNode* pre = cur->left;
while (pre->right) {
pre = pre->right;
}
pre->right = cur->right;
cur->right = cur->left;
cur->left = nullptr;
}
cur = cur->right;
}
}
};
核心就是
如果当前节点有左子树:
- 找到左子树最右边的节点 pre
- 把当前节点原来的右子树接到 pre->right
- 把左子树整体挪到 cur->right
- cur->left 置空
相当于不是一次处理完左子树,是每次整理当前左子树最右侧的那条链,然后一次次操作,通过把局部结构改成前序链表形式,最终得到 root -> left subtree -> right subtree

浙公网安备 33010602011771号