给定一个整数数组,你需要验证它是否是一个二叉搜索树正确的先序遍历序列。
你可以假定该序列中的数都是不相同的。
参考以下这颗二叉搜索树:
5
/ \
2 6
/ \
1 3
示例 1:
输入: [5,2,6,1,3]
输出: false
示例 2:
输入: [5,2,1,3,6]
输出: true
进阶挑战:
您能否使用恒定的空间复杂度来完成此题?
第一种思路:
递归处理,
线性扫描,找到第一个比根节点的值大的数的下标idx, 如果找不到说明没有右子树,
找到之后继续扫描剩下的部分,看是不是都比根节点的值要大,如果不是说明不对。
然后根据先序遍历的特点,和二叉搜索树的性质可以知道,
左子树对应的部分是 preorder[1:idx], 右子树对应的部分是 preorder[idx:],
递归往下处理即可。
时间复杂度是O(nlogn),python会超时,别的语言还不知道。
class Solution(object):
def verifyPreorder(self, preorder):
"""
:type preorder: List[int]
:rtype: bool
"""
if not preorder:
return True
if preorder == sorted(preorder) or preorder == sorted(preorder)[::-1]:
return True
#从左往右找第一个比它大的数
index = -1
for i, num in enumerate(preorder):
if num > preorder[0]:
index = i
for j in range(index, len(preorder)):
if preorder[j] <= preorder[0]:
return False
break
if index < 0:
return self.verifyPreorder(preorder[1:])
else:
return self.verifyPreorder(preorder[1:index]) and self.verifyPreorder(preorder[index:])
第二种思路:
二叉搜索树的最重要的性质:
二叉搜索树的中序遍历为升序。
所以如果我们能得到输入二叉树的中序遍历,那么就可以利用这条性质来判断是不是二叉搜索树。
那么要怎么得到中序遍历呢?
题目给定的条件为前序遍历数组,前序遍历的特点是中左右,而中序遍历的特点是左中右,
我们先假设给定二叉树就是二叉搜索树,
那么根据二叉搜索树的性质,左子树所有节点的值都比根节点的值要小,
在前序遍历里,由于遍历顺序为中左右,不断地向左下角遍历,对于左子树的部分,就会形成一段连续递减的区间,
因此可以用递减栈来解题,找到左子树的部分。
class Solution(object):
def verifyPreorder(self, preorder):
"""
:type preorder: List[int]
:rtype: bool
"""
#前序遍历顺序: 中左右
#中序遍历顺序: 左中右
if not preorder:
return True
root_val = preorder[0]
stack, res = [root_val], []
for i, num in enumerate(preorder[1:]):
# print num, stack, res
if num < stack[-1]: #比栈顶元素小,说明当前节点应该在栈顶元素的左子树里
stack.append(num) #所以当前节点的前序遍历优先级更高,让它入栈
else:
while stack:
if stack[-1] > num:
stack.append(num) #小说明优先级更高,让当前节点入栈
break
elif stack[-1] < num: #当前节点的值比栈顶元素更大,说明当前节点的父节点和父节点的左子树的部分已经全部找到了,可以逐一弹出并添加到中序遍历尾部
res.append(stack.pop())
if not stack:
stack.append(num)
while stack: 如果还有剩余的部分,也逐一弹出并添加到中序遍历尾部
res.append(stack.pop())
# print res
return res == sorted(res)