在Java的Iterator是也可以支持remove()操作 - 删除上一个访问的结点。BST删除结点的操作也可以用递归算法来解决(当然也可用平衡二叉树删除结点进行分类的解法,但是递归的解法更加巧妙)。首先我们找到被删除的结点,然后把它替换成其右子树的最小值m(目的是为了保证删除后的右子树满足比当前结点大)。然后我们再递归删除右子树的m结点。Delete Node in a BST:
如果查找的结点存在于BST上,我们很容易可以将它找出。但是如果需要查找的结点不存在与树上,我们希望返回最接近的结点,这种问题该如何解决呢?首先我们要想一个问题,对于一个在BST上的结点,比它大的值可能存在于哪里?应该是存在于这个结点的右子树或父结点(如果存在)的右子树。但是这么思考的问题是我们需要跟踪父结点的情况,这个如果不借助其他数据结构存储很难实现。我们不如换一种思路:当访问到结点时,如果值大于target就找保存左子树的最接近target的值,然后取这两个值最接近target的一个;反之就从右子树来找。同样借助递归的特性我们可以解决这个问题。Closest Binary Search Tree Value
int count = 0; publicintkthSmallest(TreeNode root, int k){ return solve(root, k); }
privateintsolve(TreeNode root, int k){ if (root == null) { return -1; } int r = solve(root.left, k); if (r != -1) return r; count++; if (count == k) { return root.val; } r = solve(root.right, k); return r; }
另一种变形是,在BST找到接近target的k个数。这个可以通过inorder来找到,但是这里介绍一种高效的方法借助额外的数据结构来解决。通过栈来存储比target小的结点,另一个栈存储大于等于target的结点。然后用类似two pointer的方法找到接近target的k个数。Closest Binary Search Tree Value II:
public List<Integer> closestKValues(TreeNode root, double target, int k){ Deque<TreeNode> greater = new ArrayDeque<>(), less = new ArrayDeque<>(); TreeNode cur = root; while (cur != null) { if (cur.val < target) { less.push(cur); cur = cur.right; } else { greater.push(cur); cur = cur.left; } } List<Integer> list = new ArrayList<>(); while (k > 0) { if (greater.isEmpty() && less.isEmpty()) { break; } elseif (greater.isEmpty()) { list.add(lessNext(less)); } elseif (less.isEmpty()) { list.add(greaterNext(greater)); } elseif (Math.abs(less.peek().val - target) < Math.abs(greater.peek().val - target)) { list.add(lessNext(less)); } else { list.add(greaterNext(greater)); } k--; } return list; }
privateintlessNext(Deque<TreeNode> stack){ TreeNode top = stack.pop(); int r = top.val; top = top.left; while (top != null) { stack.push(top); top = top.right; } return r; }
privateintgreaterNext(Deque<TreeNode> stack){ TreeNode top = stack.pop(); int r = top.val; top = top.right; while (top != null) { stack.push(top); top = top.left; } return r; }