牛客刷题日记【重建二叉树|输出二叉树的右视图|二叉搜索树与双向链表】

BM40 重建二叉树

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

思考:

用递归的方式求解;使用当前前序序列段的第一个元素,确定根元素;在中序序列中确定该元素的位置,并将前序、中序序列划分为左右子树两部分;对于左右子树进行递归计算。

代码:

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <vector>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param preOrder int整型vector 
     * @param vinOrder int整型vector 
     * @return TreeNode类
     */
    TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {
        // write code here
        
        if (preOrder.empty() || vinOrder.empty()) return nullptr;
        
        TreeNode* root = new TreeNode(preOrder[0]);

        for (int i = 0;i < vinOrder.size();i++) if (vinOrder[i] == root->val) {
            vector<int> lpre(preOrder.begin() + 1, preOrder.begin() + i + 1);
            vector<int> lvin(vinOrder.begin(), vinOrder.begin() + i);
            root->left = reConstructBinaryTree(lpre, lvin);

            vector<int> rpre(preOrder.begin() + 1 + i,preOrder.end());
            vector<int> rvin(vinOrder.begin() + 1 + i,vinOrder.end());
            root->right = reConstructBinaryTree(rpre, rvin);

        }

        return root;

    }
};

BM41 输出二叉树的右视图

请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图

数据范围: 0≤n≤100000≤n≤10000
要求: 空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

思考:

这道题目可以被拆分成两部分,首先根据前序序列和中序序列建树。

其次,对二叉树进行从右至左的层序遍历,将每层的第一个元素添加至最终的链表中。

代码:

#include <queue>
#include <vector>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 求二叉树的右视图
     * @param preOrder int整型vector 先序遍历
     * @param inOrder int整型vector 中序遍历
     * @return int整型vector
     */
    
    struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
        TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    };

    TreeNode* getTree(vector<int>& preOrder, vector<int>& inOrder) {
        if (preOrder.empty() || inOrder.empty()) return nullptr;

        TreeNode* root = new TreeNode(preOrder[0]);

        for (int i = 0;i < inOrder.size(); i++) if (inOrder[i] == root->val) 
        {
            vector<int> lpre (preOrder.begin() + 1, preOrder.begin() + 1 + i);
            vector<int> lin (inOrder.begin(), inOrder.begin() + i);

            vector<int> rpre (preOrder.begin() + 1 + i, preOrder.end());
            vector<int> rin (inOrder.begin()+ i + 1,inOrder.end());

            root->left = getTree(lpre, lin);
            root->right = getTree(rpre,rin);

        }

        return root;
    }
    
    vector<int> solve(vector<int>& preOrder, vector<int>& inOrder) {
        // write code here
        TreeNode* root = getTree(preOrder, inOrder);

        queue<TreeNode*> que;

        que.push(root);
        
        vector<int> res;

        while (!que.empty())
        {
            TreeNode* tmp = new TreeNode(-1);
            que.push(tmp);

            vector<TreeNode*> a;
            while (que.front()->val != -1) {
                a.push_back(que.front());
                que.pop();
            }

            res.push_back(a[0]->val);
            for (int i = 0;i < a.size();i++) 
            {   
                std::cout << a[i]->val << " ";
                TreeNode* r = a[i]->right;
                TreeNode* l = a[i]->left;

                if (r) que.push(r);
                if (l) que.push(l);
            }
            std::cout << endl;

            que.pop(); // -1 出队列
        }

        return res;   
    }
};

BM30 二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。

二叉搜索树= 二叉排序树, 满足中序序列递增

思考:

本题是二叉树的线索化。

核心点在于:

  1. 将前一个结点的右指针指向当前节点
  2. 将当前结点的左指针指向前一个结点

对其进行中序遍历,记录当前结点和前一个结点指针,对每个结点进行上述操作。

代码:

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
	bool flag = false;
	TreeNode* res;
	TreeNode* cur;
	TreeNode* pre;


	void in (TreeNode* root) {
		if (root == nullptr) return;

		if (root->left) in (root->left);

		if (!flag) {
			res = root;flag = true;
		}
		

		// std:: cout << root->val << " ";

		pre = cur;
		cur = root;

		if (pre) std::cout << cur->val << " " << pre->val << endl;
		else std::cout << cur->val << " " << endl ;

		cur->left = pre;
		if (pre != nullptr) pre->right = cur;
		

		if (root->right) in (root->right);

	}

    TreeNode* Convert(TreeNode* pRootOfTree) {
        
		in(pRootOfTree);

		return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值