二叉树的合法性判断(系列)
· 约 3 分钟阅读 · – 次阅读
leetcode
验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。
直接递归判断
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
def helper(root, pre_val, next_val):
if not root:
return True
if root.val >= next_val or root.val <= pre_val:
return False
return helper(root.left, pre_val, root.val) and helper(root.right, root.val, next_val)
return helper(root, float('-inf'), float('inf'))
中序遍历的思路
中序遍历得到的数组必然是从小到大有序排列的。
递归思路
时间复杂度和空间复杂度均为O(n)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
def inOrder(root):
ans = []
if not root:
return ans
ans += inOrder(root.left)
ans.append(root.val)
ans += inOrder(root.right)
return ans
ans = inOrder(root)
if not ans:
return True
for i in range(1, len(ans)):
if ans[i-1] >= ans[i]:
return False
return True
非递归思路
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack = []
p = root
pre_val = float('-inf')
while stack or p:
while p:
stack.append(p)
p = p.left
p = stack.pop()
if p.val <= pre_val:
return False
pre_val = p.val
p = p.right
return True
用C++重写一遍加深记忆,这个时候就体现出Python写代码的方便性了
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (root == nullptr){
return true;
}
stack<TreeNode*> s;
long preval = (long)INT_MIN-1;
TreeNode* p = root;
while (p != nullptr || !s.empty()){
while (p != nullptr){
s.push(p);
p = p->left;
}
p = s.top();
s.pop();
// 后面被访问的数要严格大于前一个数
// 由于int最小可能为INT_MIN, 所以preval初始化值比INT_MIN小1
// 或者对于边界值单独处理
if (p->val <= preval){
return false;
}
preval = p->val;
p = p->right;
}
return true;
}
};
二叉树的完全性检验
给定一个二叉树的 root ,确定它是否是一个 完全二叉树 。
在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的, 并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 1 到 2^h 节点之间的最后一级 h 。
层序遍历的思路
如果将完全二叉数用数组存储,那么它的节点序号是顺序的。 如果有n个节点,则最后一个节点的序号应该是n-1
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isCompleteTree(self, root: TreeNode) -> bool:
if not root:
return True
queue = collections.deque([(root, 0)])
count = 0
while queue:
size = len(queue)
for i in range(size):
p, p_index = queue.popleft()
# 完全二叉树的序号是顺序的
if count != p_index:
return False
count += 1
if p.left:
queue.append((p.left, p_index*2+1))
if p.right:
queue.append((p.right, p_index*2+2))
return True