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;
        }
    }
};

核心就是
如果当前节点有左子树:

  1. 找到左子树最右边的节点 pre
  2. 把当前节点原来的右子树接到 pre->right
  3. 把左子树整体挪到 cur->right
  4. cur->left 置空

相当于不是一次处理完左子树,是每次整理当前左子树最右侧的那条链,然后一次次操作,通过把局部结构改成前序链表形式,最终得到 root -> left subtree -> right subtree

posted @ 2026-04-29 21:51  rdcamelot  阅读(14)  评论(0)    收藏  举报