lintcode flatten-binary-tree-to-linked-list 将二叉树拆成链表 前序扁平化 中序扁平化

19 篇文章 0 订阅
5 篇文章 0 订阅

问题描述

lintcode

最后再扩展了一下中序遍历的扁平化版本。

笔记

看了半天还是比较能接受递归的解法。参考:
[LeetCode] flatten binary tree 扁平化二叉树
思路:假设以下函数

TreeNode covert2link(TreeNode *root)

可以将一棵树转化为符合要求的链表,并返回链表的尾部(链表的头部必定是root)。那么该怎么做呢?那就是:

  • 首先,调用这个函数把左子树转化为符合要求的链表,得到左子树转化成的链表的尾部。
  • 再调用这个函数把右子树转化成符合要求的链表,得到右子树转化成的链表的尾部。
  • 然后按照前序遍历的定义,将《root》–《左子树链表》–《右子树链表》按序连接起来。
  • 最后返回整个整合好的链表的尾部。

代码

笔记里的递归的解法似乎比较好懂一点

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param root: a TreeNode, the root of the binary tree
     * @return: nothing
     */
    void flatten(TreeNode *root) {
        // write your code here
        convert2link(root);
    }

    TreeNode* convert2link(TreeNode* root)
    {
        if (root == NULL)
            return NULL;
        // 首先,调用这个函数把左子树转化为符合要求的链表,得到左子树转化成的链表的尾部。
        TreeNode* leftLinkTail = convert2link(root->left);
        // 再调用这个函数把右子树转化成符合要求的链表,得到右子树转化成的链表的尾部。
        TreeNode* rightLinkTail = convert2link(root->right);
        // 然后按照前序遍历的定义,将《root》–《左子树链表》–《右子树链表》按序连接起来。
        if (leftLinkTail)
        {
            leftLinkTail->right = root->right;// 《左子树链表》–《右子树链表》
            root->right = root->left;// 《root》–《左子树链表》
        }
        root->left = NULL;
        // 最后返回整个整合好的链表的尾部
        if (rightLinkTail)
            return rightLinkTail;
        else if (leftLinkTail)
            return leftLinkTail;
        else
            return root;
    }
};

九章算法的非递归解法没有看懂

class Solution {
public:
    /**
     * @param root: a TreeNode, the root of the binary tree
     * @return: nothing
     */
    void flatten(TreeNode *root) {
        // write your code here
        if (root == NULL) return;  
        while (root) {  
            if (root->left) {  
                TreeNode *pre = root->left;  
                while (pre->right)  
                    pre = pre->right;  
                pre->right = root->right;  
                root->right = root->left;  
                root->left = NULL;  
            }
            root = root->right;
        }  
    }
};

最后扩展一下,如果要求flatten成中序遍历的顺序,该怎么做呢?我写了一个版本,感觉有点滥用了pair了,而且不知道是否正确,请高手指导指导,谢谢。

//
//  main.cpp
//  inorderBtree2Link
//
//  Created by SteveWong on 7/20/16.
//  Copyright © 2016 SteveWong. All rights reserved.
//

#include <iostream>
using namespace std;

class TreeNode
{
public:
    int val;
    TreeNode *left, *right;
    TreeNode(int val)
    {
        this->val = val;
        this->left = this->right = NULL;
    }
};

void inorder(TreeNode *root)
{
    if (root == NULL)
    {
        return;
    }
    if (root->left)
    {
        cout << root->val << " ->l " << root->left->val << endl;
    }
    if (root->right)
    {
        cout << root->val << " ->r " << root->right->val << endl;
    }
    inorder(root->left);
//    cout << root->val << ' ';
    inorder(root->right);
}

pair<TreeNode*, TreeNode*> convert2linkInorder(TreeNode *root)
{
    if (root == NULL)
    {
        return pair<TreeNode*, TreeNode*>(NULL, NULL);
    }
    pair<TreeNode*, TreeNode*> tpleft = convert2linkInorder(root->left);
    pair<TreeNode*, TreeNode*> tpright = convert2linkInorder(root->right);
    TreeNode* head = NULL;
    TreeNode* tail = NULL;
    if (tpleft.first && tpleft.second)// 有左子树
    {
        tpleft.second->right = root;
        tpleft.second->left = NULL;
        head = tpleft.first;
    }
    else //无左子树
    {
        head = root;
    }
    root->left = NULL;
    if (tpright.first && tpright.second)// 有右子树
    {
        root->right = tpright.first;
        tail = tpright.second;
    }
    else// 无右子树
    {
        tail = root;
    }
    return pair<TreeNode*, TreeNode*>(head, tail);
}


int main(int argc, const char * argv[]) {
    // insert code here...
//    std::cout << "Hello, World!\n";
    TreeNode *root = new TreeNode(0);
    TreeNode *left = new TreeNode(1);
    TreeNode *right = new TreeNode(2);
    root->left = left;
    root->right = right;
    left->left = new TreeNode(3);
    left->right = new TreeNode(4);
    right->left = new TreeNode(5);
    right->right = new TreeNode(6);
    inorder(root);
    auto res = convert2linkInorder(root);
    cout << "inorder" << endl;
    inorder(res.first);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值