递归 面试题:已知两个遍历 建立树

例如已知先序遍历求中序遍历;
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

思路其实挺简单的,每次在pre中找根结点,在inorder找左节点与右节点


#include <iostream>
#include<vector>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};


class Solution {
private:
	TreeNode* _buildTree(vector<int>& preorder, int preLeft, int preRight, vector<int>& inorder, int inLeft, int inRight)
	{

		if (preLeft>preRight||inLeft>inRight)
		{
			return nullptr;
		}
		TreeNode *root = new TreeNode(preorder[preLeft]);
		
		int index;
		for (index = inLeft;index <= inRight;index++)//找到了先序在中序中的位置
		{
			if (preorder[preLeft]==inorder[index])
			{
				break;
			}
		}

		root->left= _buildTree(preorder, preLeft+1, preLeft+ index -inLeft, inorder, inLeft, index-1);
		root->right = _buildTree(preorder, preLeft + index - inLeft + 1, preRight, inorder, index + 1, inRight);
		return root;
	}

public:
	TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
	{
		int preLeft = 0;
		int preRight = preorder.size() - 1;

		int inLeft = 0;
		int inRight = inorder.size() - 1;

		
		return  _buildTree(preorder, preLeft, preRight, inorder, inLeft, inRight);

	}
};




当然每次根据pre在in中找位置可能太浪费时间,我们采用空间换时间,采用unorderrd_map存取中序的位置



class Solution {
private:
	TreeNode* _buildTree(vector<int>& preorder, int preLeft, int preRight, unordered_map<int, int> &index_map, int inLeft, int inRight)
	{//index_map 必须用引用,可能内存占用大

		if (preLeft>preRight||inLeft>inRight)
		{
			return nullptr;
		}
		TreeNode *root = new TreeNode(preorder[preLeft]);
		
		int index= index_map[preorder[preLeft]];
	

		root->left= _buildTree(preorder, preLeft+1, preLeft+ index -inLeft, index_map, inLeft, index-1);
		root->right = _buildTree(preorder, preLeft + index - inLeft + 1, preRight, index_map, index + 1, inRight);
		return root;
	}

public:
	TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
	{
		int preLeft = 0;
		int preRight = preorder.size() - 1;

		int inLeft = 0;
		int inRight = inorder.size() - 1;

		unordered_map<int, int> index_map;
		for (int i = 0;i < inorder.size();i++)
		{
			index_map[inorder[i]] = i;
		}
		
		return  _buildTree(preorder, preLeft, preRight,  index_map, inLeft, inRight);

	}
};

当然还有 已知后序和中序,建立二叉树。

思路一样首先在后序中倒数第一个是根,然后在中序中找左右子节点,递归

代码如下:

/**
 * 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 {
private:
	TreeNode* _buildTree(vector<int>&  postorder, int posLeft, int posRight, vector<int>&  inorder, int inLeft, int inRight)
	{
		if (posLeft > posRight || inLeft > inRight)
		{
			return nullptr;
		}
		TreeNode *root = new TreeNode(postorder[posRight]);
		int index;
		for (index=inLeft;index<=inRight;index++)//由于是后序遍历,所以是左右根
		{
			if (postorder[posRight]==inorder[index])
			{
				break;
			}
		}
		root->left= _buildTree(postorder, posLeft, posRight+index-inRight-1, inorder, inLeft, index-1);
		root->right = _buildTree(postorder, posRight + index - inRight, posRight  - 1, inorder,  index +1,inRight);
		return root;
		//

	}
public:
	TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
	{
		int posLeft = 0;
		int posRight = postorder.size() - 1;

		int inLeft = 0;
		int inRight = inorder.size() - 1;


		return  _buildTree(postorder, posLeft, posRight, inorder, inLeft, inRight);

	}
};

当然也可以进行优化采用undered_map保存中序的数值和下标的关系


#include <iostream>
#include<vector>
#include<unordered_map>
using namespace std;

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
private:
	TreeNode* _buildTree(vector<int>&  postorder, int posLeft, int posRight, unordered_map<int, int> &index_map, int inLeft, int inRight)
	{
		if (posLeft > posRight || inLeft > inRight)
		{
			return nullptr;
		}
		TreeNode *root = new TreeNode(postorder[posRight]);
		int index= index_map[postorder[posRight]];
		
		root->left= _buildTree(postorder, posLeft, posRight+index-inRight-1, index_map, inLeft, index-1);
		root->right = _buildTree(postorder, posRight + index - inRight, posRight  - 1, index_map,  index +1,inRight);
		return root;
		//

	}
public:
	TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
	{
		int posLeft = 0;
		int posRight = postorder.size() - 1;

		int inLeft = 0;
		int inRight = inorder.size() - 1;

		unordered_map<int, int> index_map;
		for (int i = 0;i < inorder.size();i++)
		{
			index_map[inorder[i]] = i;
		}

		return  _buildTree(postorder, posLeft, posRight, index_map, inLeft, inRight);

	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值