调整搜索二叉树中的两个错误的节点 & 统计完全二叉树的节点数
调整搜索二叉树中的两个错误的节点
《程序员代码面试指南》第41题 P137 难度:尉★★☆☆
(只看原问题,进阶问题难度将,解答不可能看的懂)
如果没有错误节点,那么搜索二叉树的中序遍历的节点值是一直升序的。如果有两个节点位置错了,就一定会出现降序。
出现降序有2种情况:
- 出现2次降序,第一个错误的节点为第一次降序时较大的节点,第二个错误的节点为第二次降序时较小的节点
- 出现1次降序,第一个错误的节点为这次降序时较大的节点,第二个错误的节点为这次降序时较小的节点
总结为:第一个错误的节点为第一次降序时较大的节点,第二个错误的节点为最后一次降序时较小的节点。
因此只需要改写一个基本的中序遍历即可。书上代码使用了非递归(栈)来进行中序遍历,代码如下:
public Node[] getTwoErrNodes(Node head) {
Node[] errs = new Node[2];
if (head == null) {
return errs;
}
Stack<Node> stack = new Stack<Node>();
Node pre = null;
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
if (pre != null && pre.value > head.value) {
errs[0] = errs[0] == null ? pre : errs[0];
errs[1] = head;
}
pre = head;
head = head.right;
}
}
return errs;
}
统计完全二叉树的节点数
题目:完全二叉树的节点个数
《程序员代码面试指南》第55题 P176 难度:尉★★☆☆
遍历整棵树不是最优解法,哭了。最优解真想不出来┭┮﹏┭┮
书上的解法可以做到时间复杂度为O(h2),具体过程如下:
- 如果head==null,空树直接返回0。
- 如果不是空树,就求树的高度,即找到树的最左节点看能到哪一层,层数记为h。
- 这一步的递归过程是求解的主要逻辑,找到node右子树的最左节点。分为两种情况:
- 能到达最后一层,说明node的整棵左子树都是满二叉树,层数为h-l,节点数为2h-l-1,加上node节点自己,节点数为2h-l个。再递归去求node右子树的节点数即可。
- 不能到达最后一层,说明node的整棵右子树都是满二叉树,层数为h-l-1,节点数为2h-l-1-1,加上node节点自己,节点数为2h-l-1个。再递归去求node左子树的节点数即可。
全部过程参照如下代码:
public int nodeNum(Node head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
public int bs(Node node, int l, int h) {
if (l == h) {
return 1;
}
if (mostLeftLevel(node.right, l + 1) == h) {
return (1 << (h - l)) + bs(node.right, l + 1, h);
} else {
return (1 << (h - l - 1)) + bs(node.left, l + 1, h);
}
}
public int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}

浙公网安备 33010602011771号