剑指offer——创建二叉树

/**************************************2018/12/13*****************************************/

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

 

逻辑分析:

二叉树的前序遍历顺序是:先访问根节点,然后前序遍历左子树,再前序遍历右子树。

中序遍历顺序是:中序遍历根节点的左子树,然后是访问根节点,最后中序遍历右子树

所以有:

1、二叉树的前序遍历序列(的第一个值)一定是该树的根节点

2、中序遍历序列中根节点前面一定是该树的左子树,后面是该树的右子树

 

该题目可以使用递归的思想,所以首先介绍一下递归:(其实百度讲的很详细的说~)

特点:程序之间或间接调用自身

适应于:子问题与原问题相似(即将大型复杂的问题层层转化为与原问题相似的规模较小的问题来解决)

代码组成:边界条件,递归前进段,递归返回段---------------边界条件不满足时递归前进、满足时递归返回

递归练习:

1、求阶乘

int factorial(int val)
{
    int res=1;
    if (val > 0) {

        res=val*jiecheng(val-1);
        
    }
    return res;
}

int main()
{
    int pre=5;
    int out=1;
    out=factorial(pre);
    printf("%d", out);
    system("pause");
    return 0;
}

解析:

2、将一个int型数组倒序输出,例如输入数组{1,2,3,4,5},输出数组{5,4,3,2,1};

代码为:

void rev(const vector<int> &v, int pos, vector<int> &res)
{
	if (pos != v.size() - 1)
		rev(v, pos + 1,res);
	res.push_back(v[pos]);
}

int main()
{
	vector<int> v{ 1,2,3,4,5,6,7 };
	vector<int> res;
	rev(v, 0, res);
	for (auto c : res)
		cout << c << endl;
	return 0;
	
}

解析:

3、计算二叉树节点数值之和(节点数值大于零)

 

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

};
int sum(TreeNode *root)
{

    if(root==NULL) return 0;
    else 
    {

        return root->val+sum(root->left)+sum(root->right);

     }

}

解析:

所以本题:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
		
		int temp = 0;
		int vin_index = 0;
		int len = 0;
		vector<int> vin_left{}, vin_right{}, pre_left{}, pre_right{};
		len = vin.size();
		vin_index = len;

		if (len == 0) return NULL;
		else
		{
			for (temp = 0; temp < len; temp++)
			{
				if (vin[temp] == pre[0])
					break;
			}
			vin_index = temp;
			for (temp = 0; temp < len; temp++)
			{
				if (temp < vin_index)
				{
					vin_left.push_back(vin[temp]);
					pre_left.push_back(pre[1 + temp]);
				}
				else if (temp > vin_index)
				{
					vin_right.push_back(vin[temp]);
					pre_right.push_back(pre[temp]);
				}
				else;
			}
			TreeNode* tn = new TreeNode(pre[0]);
			tn->left = reConstructBinaryTree(pre_left, vin_left);
			tn->right = reConstructBinaryTree(pre_right, vin_right);
			return tn;
		}
	}
};

或者:

链接:https://www.nowcoder.com/questionTerminal/8a19cbe657394eeaac2f6ea9b0f6fcf6
来源:牛客网

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
         
        if(startPre>endPre||startIn>endIn)
            return null;
        TreeNode root=new TreeNode(pre[startPre]);
         
        for(int i=startIn;i<=endIn;i++)
            if(in[i]==pre[startPre]){
                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
                      break;
            }
                 
        return root;
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值