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就是要找的。这个解好像效率不高的样子。