98 验证二叉搜索树
解法一:进行中序遍历:左中右。并将元素按顺序存到数组里,那么如果是二叉搜索树的话,得到的这个数组就是有序的。用递归来做,这样的坏处就是需要创建很多中间数组,在空间上消耗会大一些。
// 92ms 61.07% 41.4mb 6.92%
var inorder = function (root){
if (!root){
return []
}
return inorder(root.left).concat(root.val).concat(inorder(root.right))
}
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isValidBST = function(root) {
let inorderList = inorder(root)
for (i = 0; i < inorderList.length-1; i++){
if (inorderList[i] >= inorderList[i+1]){
return false
}
}
return true
};
解法2:也是中序遍历,但是每次只要比较前一个节点,省去了创建临时数组的那些操作,所以空间上会节省一些。
// 84ms 75.43% 37.2mb 79.87%
var isValidBST = function(root){
let pre = null
let helper = function(root){
if (!root){
return true
}
if (!helper(root.left)){
return false
}
if (pre !== null && pre >= root.val){
return false
}
pre = root.val
return helper(root.right)
}
return helper(root, pre)
}
235 二叉搜索树的最近公共祖先
因为有二叉搜索树这个特点,因此,那么如果根节点比q,p都大,那么答案肯定在左子树上,如果比qp都小,那么肯定就在右子树上,否则,就是qp一个在左变一个在右边,那么此时的根节点就是qp最近的根节点。
// 84ms 96.65% 43.6mb 73.15%
var lowestCommonAncestor = function(root, p, q) {
if (root.val > p.val && root.val > q.val){
return lowestCommonAncestor(root.left, p, q)
}else if(root.val < p.val && root.val < q.val){
return lowestCommonAncestor(root.right, p, q)
}
return root
};
也可以不写成递归的形式,两者逻辑是一样的。时间空间都差不多
var lowestCommonAncestor = function(root, p, q) {
while (true){
if (root.val > p.val && root.val > q.val){
root = root.left
}else if(root.val < p.val && root.val < q.val){
root = root.right
}else{
return root
}
}
};
236. 二叉树的最近公共祖先
// 112ms 24.19% 41.4mb 43.56%
var lowestCommonAncestor = function(root, p, q) {
if (root === null || root.val === q.val || root.val === p.val){
return root
}
let left = lowestCommonAncestor(root.left, p, q)
let right = lowestCommonAncestor(root.right, p, q)
if (left === null){
return right
}else if (right === null){
return left
}else{
return root
}
};
对比235,总之就是那个道理,如果有一个pq分别在root的左右两边,那么root就是要找的。这个解好像效率不高的样子。