【leetcode】114. 二叉树展开为链表( Flatten Binary Tree to Linked List)


题目描述

【leetcode】114. 二叉树展开为链表( Flatten Binary Tree to Linked List)

给定一个二叉树,原地将它展开为链表。

例如,给定二叉树

    1
   / \
  2   5
 / \   \
3   4   6

将其展开为:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

第一次解答

思路
递归,该方法的主要思想是从叶子结点开始,把右子树连接到左子树的末尾,自底向上,保证每向上一层,下面的结点都已经展平。展开一棵根节点为root的二叉树可划分为如下子问题:

  1. 展开root的右子树
  2. 展开root的左子树
  3. 找到root的左子树的最后一个结点,将该结点的右孩子指向root的右子树
  4. 将root的右孩子指向root的左孩子
  5. 将root的左孩子指向空
  6. 递归的进行上面1-5步,直到树展平。

上述过程中,为了突出主要思路,忽略了许多细节,如指针是否为空的判断,停止条件等,详情见代码。

test case:
[1,2,5,3,4,null,6]
[]

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    // 展开一棵树,并返回树末尾结点指针
    TreeNode* dfs(TreeNode *root){
        if(nullptr == root)
            return nullptr;
        // 叶子结点,已经是展平的了,末尾结点为root
        if(nullptr == root->left && nullptr == root->right)
            return root;

        // 非叶子结点,把左右两边展平,并返回末尾结点指针
        TreeNode* right_end = dfs(root->right);
        TreeNode* left_end = dfs(root->left);
        // 若左子树不为空,则把展平后的右子树连接到展平后的左子树末端。
        if(nullptr != left_end){
            left_end->right = root->right;
            root->right = root->left;
            root->left = nullptr;
        }

        // 返回最末尾的结点指针
        if(nullptr == right_end) 
            return left_end;
        else
            return right_end; 
    }
    void flatten(TreeNode* root) {
        dfs(root);
        return;
    }
};

结果:
截图

第二次解答

思路
看到有人说递归也需要额外的空间,可以不需要递归完成递归这题,启发了我。
迭代方法。大体思想是不断地把右子树拼接到左子树的末尾,是一种自顶向下的方法:

  1. 首先明确:根据题意,展开的链表的顺序与二叉树前序遍历的顺序相同。
  2. 从根节点出发,找到左子树前序遍历最后访问的结点p
  3. 将p的右孩子指向根节点的右子树
  4. 将根节点的右孩子指向根节点的左子树
  5. 将根节点的左孩子指向空
  6. 根节点向右步进一位,即root = root->right
  7. 重复迭代2-6步,直到root为空,则树展开完成

同样地,上述过程中,为了突出主要思路,忽略了许多细节,如指针是否为空的判断,停止条件等,详情见代码。

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        // 从根节点出发
        while(nullptr != root){
        	// 找到左子树的末尾结点
            TreeNode *p = root->left;
            while(nullptr != p){
                if(nullptr != p->right) p = p->right;
                else if(nullptr != p->left) p = p->left;
                else break;
            }
            // 若左子树不为空,则把右子树连接到左子树末端
            if(nullptr != p){
                p->right = root->right;
                root->right = root->left;
                root->left = nullptr;
            }
            // 根节点向前步进一格
            root = root->right;
        }
        return;
    }
};

结果:
在这里插入图片描述

相关/参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值