栈和队列---构造数组的MaxTree

该博客介绍了如何使用栈来构造数组的MaxTree,即一棵每个子树上最大值节点为树头的二叉树。文章详细阐述了构造原则,通过从左到右遍历数组,利用栈保存元素并判断其左右最大值,最终达到O(N)的时间复杂度和O(N)的额外空间复杂度。
摘要由CSDN通过智能技术生成

【题目】

  定义二叉树节点如下:

class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

  一个数组的MaxTree定义如下:
  1、数组中必须没有重复元素
  2、MaxTree是一棵二叉树,数组的每一个值对应一个二叉树的节点
  3、包括MaxTree树在内且在其中的每一棵子树上,值最大的节点就是树的头。
  给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的函数,要求如果数组长度为N,则时间复杂度为O(N)、额外空间复杂度为O(N)。

【基本思路】

  使用以下原则建立这棵树:
  
  1、每一个数的父节点是它左边第一个比它大的数和它右边第一个比它大的数中,较小的一个。
  2、如果一个数左边没有比它大的数,右边也没有,那么这个数就是整个数组中的最大值,那么这个数是MaxTree的头节点。

  接下来的只要知道每一个数左边比它大的数以及右边比它大的数,剩下的工作就很好实现了。如何实现呢?使用栈。
  
  从左到右遍历数组arr,假设遍历到的位置为i,如果栈为空或者栈顶元素大于arr[i],直接将arr[i]压入栈中;否则将栈中小于arr[i]的元素全部出栈,然后压入arr[i]。同时,栈中元素的左边第一个比它大的数就是它相邻的数,右边第一个比它大的数就是使它出栈的数,如果没有数使它出栈,说明它右边没有比它大的数。

  以[3,1,2]为例,首先3入栈,接下来1比3小,直接入栈,并且确定了1左边第一个比它大的数是3;接下来2比1大,1出栈,同时可以确定1右边第一个比它大的数是2;接下来2比3小,2入栈,并且确定了2左边第一个比它大的数是3。此时栈中的元素为[3,2],没有数使它们出栈,所以3和2右边都没有比它大的数。

【代码实现】

#python3.5
class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

def getMaxTree(arr):
    nArr = [Node(arr[i]) for i in range(len(arr))]
    lBigMap = {}
    rBigMap = {}
    stack = []
    for i in range(len(nArr)):
        curNode = nArr[i]
        while stack and stack[-1].value < curNode.value:
            cur = stack.pop()
            lBigMap[cur] = stack[-1] if stack else None
            rBigMap[cur] = curNode
        stack.append(curNode)
    while stack:
        cur = stack.pop()
        lBigMap[cur] = stack[-1] if stack else None
        rBigMap[cur] = None
    head = None
    for i in range(len(nArr)):
        curNode = nArr[i]
        left = lBigMap[curNode]
        right = rBigMap[curNode]
        if left == None and right == None:
            head = curNode
        elif left == None:
            if right.left == None:
                right.left = curNode
            else:
                right.right = curNode
        elif right == None:
            if left.left == None:
                left.left = curNode
            else:
                left.right = curNode
        else:
            parent = left if left.value < right.value else right
            if parent.left == None:
                parent.left = curNode
            else:
                parent.right = curNode
    return head
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值