LeetCode-树的构造篇

树的创建一定是递归创建分而治之
刷题顺序遵循
https://blog.csdn.net/linhuanmars/article/details/41040087

1.LeetCode108,将有序数组转换为二叉搜索树

对于该题一个比较朴素的想法就是讲每棵树的左右子树的节点数量差控制在一个节点范围内,即每次将数组arr分成(arr-1)/2和arr-(arr-1)/2-1两个子树,然后数组中间节点作为根节点

def build(arr[],l,r):
	if l>r:
		return None
	mid=l+(r-l)/2
    root=TreeNode(arr[mid])
    root.left=build(arr,l,mid-1)
    root.right=build(arr,mid+1,r)
    return root
public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
 }
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return build(nums,0,nums.length-1);
    }
    private TreeNode build(int[] nums,int l,int r){
        if(l>r)
            return null;
        int mid=l+(r-l)/2;
        TreeNode node=new TreeNode(nums[mid]);
        node.left=build(nums,l,mid-1);
        node.right=build(nums,mid+1,r);
        return node;
    }
}

Java与C++区别,写C++的数组一般用vector,Java里面直接用arr[],和 C很像,int[] arr

LeetCode109,将有序链表转换为二叉搜索树
同样的思路,将数组分成两部分,在进入链表前记录链表的长度n,将前n/2的元素放入左子树,第n/2+1作为当前节点,剩下的元素作为右子树,同时保证进入左右子树时元素大于0,否则赋值为0

TreeNode* build(ListNode* head,int n){
        int i=0;
        ListNode *cur=head;
        while(i<n/2){
            i++;
            cur=cur->next;
        }
        TreeNode *cur_=new TreeNode(cur->val);
        if(n/2>0)
            cur_->left=build(head,n/2);
        else
            cur_->left=NULL;
        if((n-n/2-1)>0)
            cur_->right=build(cur->next,n-n/2-1);
        else
            cur_->right=NULL;
        return cur_;
    }

再补一块关于C++ new运算符,该运算符返回的是一个指针
//Allocates size bytes of storage, suitably aligned to represent any object of that size, and returns a non-null pointer to the first byte of this block.

LeetCode 105
从前序和中序序列中恢复二叉树

def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if len(preorder)==0:
            return None
        mid=0
        for i in range(len(inorder)):
            if inorder[i]==preorder[0]:
                mid=i
        root=TreeNode(preorder[0])
        root.left=self.buildTree(preorder[1:mid+1],inorder[:mid])
        root.right=self.buildTree(preorder[mid+1:],inorder[mid+1:])
        return root

树的前序为根左右,中序为左根右,加上树的构造都是递归,所以我们的想法是将前序分成当前节点+左子树+右子树,中序分成左子树+当前节点+右子树,一个朴素 的想法是拿着根去中序中将树分隔开

def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if inorder:
            root = TreeNode(preorder.pop(0))
            ind = inorder.index(root.val)
            root.left = self.buildTree(preorder,inorder[:ind])
            root.right = self.buildTree(preorder,inorder[ind+1:])
            return root

在力扣上看别人写的
list pop(index)方法,从list中删除下标为index的元素,并返回list[index]
list index() 函数用于从列表中找出某个值第一个匹配项的索引位置,则此时右子树可以被分隔开
此时还利用到python默认传引用的技巧,当左子树完全处理完时,所有左子树即可被pop完

LeetCode106
从中序和后序恢复二叉树

def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        if inorder:
            root=TreeNode(postorder.pop(-1))
            index=inorder.index(root.val)
            root.right=self.buildTree(inorder[index+1:],postorder)
            root.left=self.buildTree(inorder[:index],postorder)
            return root

类似的,只是这次是先构建右子树,后构建左子树,但是不要忘记判断中序是否为空

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值