Leetcode刷题之路(Python)—— 654. Maximum Binary Tree

题目的连接:https://leetcode.com/problems/maximum-binary-tree/description/

       “Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:
            1. The root is the maximum number in the array.
            2. The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.
            3. The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.
      Construct the maximum tree by the given array and output the root node of this tree.”

      现在有一个整型数组,组内数字不重复。要根据这个数组来构造一棵数满足以下的条件:
            1.根是这个数组中最大的数
            2.左子树是由上一步得出的最大的数左边的数组组成的树
            3.右子树是由上一步得出的最大的数右边的数组组成的树
      根据给定的数组,构造最大二叉树,并输出结点
      给出的例子的一个数组:[3,2,1,6,0,5],画出的树就像这样:

  6
/   \
3     5
\    / 
 2  0   
   \
    1

最后程序要输出的结果,就是这个树按层遍历的结果,也就是[6,3,5,null,2,0,null,null,1]

解题思路

      每次都选最大的数,分左右,进行迭代。本质就是一个二叉树的递归。用python写迭代要知道一个点:默认的python有一个可用的递归深度的限制(在我的环境下是1000),用来避免耗尽计算机中的内存。所以我们在写递归的时候一定要把递归结束的条件限制好。在此题目中还有一个Note,写着“The size of the given array will be in the range [1,1000]”,我想也可能是为了顾及这一点。

  • 每次最大的数要怎么获取?
         python中有max()函数,参数为一个list,可以求这个list中最大的数。我们就用给的example来思考一下:

     nums是我们的输入数组[3,2,1,6,0,5]。那么树的肯定就是“6”了。接下来以“6”为界限,把数组分成两个:[3,2,1]和[0,5]。那么[3,2,1]整体就在6的左边,[0,5]整体就在6的右边。

       我们先看[3,2,1]这个list。又要重新用max函数,得到此刻数组的最大值“3”。以“3”为分界点再分成两个数组,[]和[2,1]。此时我们可以看出“3”左边已经没有东西了,所以“3”的左子树为null.右边的[2,1]继续分解。[2,1]最大的数是“2”“2”的左边没有数了,所以“2”的左子树为null,右子树为“1”“1”的左右都是null。
       [0,5]这个list与上面的原理相同。经过这些分析之后,我们就可以得到上面的那个树。

  • 每次改变的list要怎么存储
         经过上一步的分析,我们知道要用max函数。但是max函数有个问题,每次取得最大值的list是不固定的。比如第一次取[3,2,1,6,0,5]的最大数,第二次就取[3,2,1]的最大数……我们要解决的问题是:怎么去存储要取最大值的这个list。根据二叉树递归的经验,我们可以得知递归的时候需要list的开始位置和结束位置,既然每次我们都传进来了这两个位置, 我们就用这两个位置来识别要取最大值的list。
tmp=[]
for i in range(start,end):
    tmp.insert(i,nums[i])
numax=max(tmp)

      tmp存储每次要取最大值的list。每次锁定位置后,将初始nums的相对位置的数,插入到tmp中。numax此时就是我们要找的,现在的list的最大值。

  • 怎么递归?
          以每个节点为单元进行递归。读到最大值之后,先把它变成树的结构:node=TreeNode(numax)
    再分析它的左边:node.left = spiltree(nums,start,nums.index(numax))
    然后分析右边:node.right = spiltree(nums,nums.index(numax)+1,end)
    每分析完一个节点,就返回它。
node=TreeNode(numax)
node.left = spiltree(nums,start,nums.index(numax))
node.right = spiltree(nums,nums.index(numax)+1,end)
return node 

以下是可执行并ac过的完整代码:

# Definition for a binary tree node.
#class TreeNode(object):
#    def __init__(self, x):
#        self.val = x
#        self.left = None
#        self.right = None

class Solution(object):
    def constructMaximumBinaryTree(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        def spiltree(nums,start,end):
            if start>=end:
                return None
            tmp=[]
            for i in range(start,end):
                tmp.insert(i,nums[i])
            numax=max(tmp)
            node=TreeNode(numax)
            node.left = spiltree(nums,start,nums.index(numax))
            node.right = spiltree(nums,nums.index(numax)+1,end)
            return node 
        return spiltree(nums,0,len(nums))

ac截图:


这里写图片描述
这里写图片描述

改进

      虽然ac了,但是我的运行时间也太慢了吧!可以说是pythoner里面拖后腿的了!绝对不允许啊。来分析分析时间长的原因吧~

  • 首先肯定是递归很费时间,不断调用自身。
  • 中间有一个for 循环,for 循环里面还执行了insert函数,还是每次递归都要执行的,这个应该是占了大头
  • 调用max函数也会消耗时间。但是这个不可避免。
  • 用python解题,写得跟用java似的,不够pythonic。

      所以第一步我先把上面tmp这个list的循环赋值换乘切片:

for i in range(start,end):
    tmp.insert(i,nums[i])
#把上面的循环换成下面的切片赋值:
tmp=nums[start:end]

      换完之后从原来的1059ms,变成了799ms,也算是一个进步。

GOOD LUCK FOR YOU ~

                                                               memoryjdch编辑于2017.10.20
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值