题目地址:
https://www.lintcode.com/problem/inorder-predecessor-in-bst/description
给定一棵BST,再给定其中一个节点p,求其中序遍历的前驱节点。
中序遍历的前驱节点的意思是,比p小的所有节点里取最大的,也就是以p为根的子树的左子树的最右边的节点。如果p左子树为空,并且p是其父亲的右儿子,那就是p的父亲;如果p左子树为空,并且p是其父亲的左儿子,那整棵树中就不存在p的前驱,返回null。所以可以先设一个前驱指针,这个指针的用处是,在找到p的左子树后,跟在另一个指针后面,然后让另一个指针向右探路直到走到null。
详细说来算法是这样的:设原树树根为root。
如果p小于等于root,那么此时p的左子树一定在root的左边,所以root向左走一步;
如果p大于root,这里分两种情况:
1、如果root已经在p的左子树里了(准确的说root或者是p左子树根,或者是左子树的右链里,右链指的是从树根一路向右走经过的节点),那就开另一个指针pred跟在root后面,然后root一路向右走直到走到null,最后返回那个跟在root后面的指针即可。
2、如果root在p的左上方,那也像上面一样操作开个指针跟在root后面,然后root一路向右走,直到root大于等于p为止。
最后,当root等于null的时候,要么说明root走到了p的空的左子树上,此时pred是p的左父亲,所以返回pred;要么root走到了p的左子树的最右边的节点的右null孩子,此时pred就是p的左子树的最右边的节点,所以也返回pred;要么root一路向左走到了null,说明p已经是最小值了,没有前驱,此时pred是默认值null,所以也返回pred。代码如下:
public class Solution {
/**
* @param root: the given BST
* @param p: the given node
* @return: the in-order predecessor of the given node in the BST
*/
public TreeNode inorderPredecessor(TreeNode root, TreeNode p) {
// write your code here
TreeNode pred = null;
while (root != null) {
if (root.val >= p.val) {
root = root.left;
} else {
// 此时root.val < p.val
pred = root;
root = root.right;
}
}
return pred;
}
}
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
时间复杂度 O ( h ) O(h) O(h),空间 O ( 1 ) O(1) O(1)。