177 把排序数组转换为高度最小的二叉搜索树

原题网址:https://www.lintcode.com/problem/convert-sorted-array-to-binary-search-tree-with-minimal-height/description

描述

给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树。

There may exist multiple valid solutions, return any of them.

您在真实的面试中是否遇到过这个题?  是

样例

给出数组 [1,2,3,4,5,6,7], 返回

     4
   /   \
  2     6
 / \    / \
1   3  5   7

标签
二叉树
递归
Cracking The Coding Interview
 
思路:二叉树问题日常懵比……最开始想的是从头开始遍历数组,一个节点一个节点的建立二叉树,后来,后来当然是做不下去了……
在网上看了别人的答案后有了思路,自己把代码写了出来,总结下:创建二叉树应该先建立根节点,再挂载左右孩子。而不是先创建左右孩子再记录更新根节点。
 
嗯……要创建二叉搜索树首先要创建根节点,哪个元素是根节点呢?
二叉搜索树的定义:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。   转自此文
 
所以根节点应该是数组索引中间值,左边的元素是左子树,右边的元素是右子树。对左右子树的创建也是同理,先创建根节点(中间值),二分后左边元素是左子树,右边元素是右子树,重复这个二分过程直到所有元素创建完毕。以上思路可用递归来实现。(树的很多问题都是递归啊)
 
AC代码:
/**
 * 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 A: an integer array
     * @return: A tree node
     */
    TreeNode * sortedArrayToBST(vector<int> &A) {
        // write your code here
    if (A.empty())
    {
        return NULL;
    }

    int ed=A.size()-1;
    int mid=ed/2;
    TreeNode * newroot=builtTree(A,0,ed);

    return newroot;
    }
    
    TreeNode * builtTree(vector<int> &A,int st,int ed)
{
    if (st>ed)
        {
            return NULL;
        }
    int mid=(st+ed)/2;
    TreeNode * newroot=new TreeNode(A[mid]);
    newroot->left=builtTree(A,st,mid-1);
    newroot->right=builtTree(A,mid+1,ed);
    return newroot;
}
};

此外,对于这种牵涉数组首尾位置的运算,最好能令首尾位置作为形参参与运算。例如之前我们见到的“搜索区间”的问题(详见:点击打开链接)就是在求左右两侧的界限时,将数组一分为二,分别令首尾位置作为形参。这是一种标准的解决办法!

那么,这道题就不难了,也采取定义新的辅助函数的方法,将首尾位置作为形参。   转自此文

其他参考:https://blog.csdn.net/lfj17/article/details/70146866

https://blog.csdn.net/yaomf/article/details/70257108

https://blog.csdn.net/lyy_hit/article/details/49660671

 
PS:参考里的答案都是在sortedArrayToBST 函数里先创建根节点,再调用递归函数:

TreeNode *newroot=new TreeNode(A[mid]);//第一个节点;
newroot->left=builtTree(A,0,mid-1);
newroot->right=builtTree(A,mid+1,ed);

而我是直接调用递归函数。区别大概就是返回的根节点是堆区建立的还是栈区建立的?不太懂,求高手指教……
 
另外,最开始用递归实现buildTree函数时,我写成了如下形式:
void buildTree(TreeNode * newroot, vector<int> &A,int st,int ed)
{
    if (st>ed)
    {
        return ;
    }
    int mid=(st+ed)/2;
    newroot=new TreeNode(A[mid]);
    buildTree(newroot->left,A,st,mid-1);
    buildTree(newroot->right,A,mid+1,ed);
}

/* --------- sortedArrayToBST函数内调用 --------- */

TreeNode * newroot=NULL;
builtTree(newroot,A,0,ed);

 
        

//int ed=A.size()-1;
//int mid=ed/2;
//TreeNode *newroot=new TreeNode(A[mid]);//第一个节点;

//builtTree(newroot->left,A,0,mid-1);
//builtTree(newroot->right,A,mid+1,ed);

 

即指针做形参,并且在函数内通过new来给形参赋值。但这样做是没用的,因为地址值传递不到实参那里,所以运行程序直接返回了NULL。在sortedArrayToBST内创建根节点运行后只返回数组中间值。

 

转载于:https://www.cnblogs.com/Tang-tangt/p/9180166.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值