【题目】
定义二叉树节点如下:
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