二叉树基础面试题【2】
今天写了几个难度升级的题,赶脚到有点点头tu了,也总结的一丢丢写二叉树的经验,下面会写到~
1.非递归先序遍历二叉树
1>算法思想:
非递归一般都会用栈来解决问题。
(1)首先创建一个栈,定义一个cur从root节点开始遍历
(2)如果cur不为空则将遍历过得cur入栈并打印,然后使cur一直遍历左孩子。
(3)如果cur为空并且栈不为空,则将栈顶元素出栈,并开始遍历其右孩子。
(4)当栈为空时,完成先序遍历。
2>算法实现
void binaryTreePrevOderNonR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode top = null;
//保证走到right还有循环
while (cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
System.out.print(cur.value + " ");
cur = cur.left;
}
top = stack.pop();
cur = top.right;
}
}
2.非递归中序遍历二叉树
1>算法思想:
中序遍历得非递归和先序遍历的思想如出一辙,唯一改变的就是打印root值得位置,中序遍历是在遍历完左子树之后再输出。
2>算法实现
void binaryTreeInOderNonR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode top = null;
while (cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
top = stack.pop();
System.out.print(top.value + " ");
cur = top.right;
}
}
3.非递归后序遍历二叉树
1>算法思想
(1)后序遍历需要遍历完成左右子树后才能出队列。
(2)所以要在左子树遍历完以后得到栈顶元素top但不出栈,判断该top是否为空,为空才能出栈并打印。
(3)如果top不为空继续遍历右孩子。
2>注意
(1)在遍历的时候有打印完以后需要将cur重新置位null,否则上一次打印的cur又会被入栈,导致死循环。
(2)如果右子树已经被打印过,就不需要再遍历右,所有定义了一个prev,如果打印过则将prev置位cur,下次进入右子树遍历的时候,判断cur.right == prev,如果成立则不需要再向下遍历,直接打印即可。
3>算法实现
void binaryTreePostOderNonR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode prev = root;
while (cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.peek();
if (cur.right == null || cur.right == prev) {
stack.pop();
System.out.print(cur.value + " ");
//prev记录是否已经被打印过,打印过则不再走他的right
prev = cur;
//保证打印过得cur不再被push到队列中
cur = null;
} else {
cur = cur.right;
}
}
}
4.层序遍历
void binaryTreeLevelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.offer(root);
}
while (!queue.isEmpty()) {
//拿到对头元素 把队头元素出栈输出
TreeNode cur = queue.poll();
System.out.println(cur.value + " ");
//拿到队头的左右子树
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
}
}
5.判断当前树是否是完全二叉树
1>算法思想
完全二叉树即相邻两个节点之间没有null节点。
(1)申请一个队列,如果root节点不为空就入栈。
(2)如果栈不为空,将栈顶元素top出栈,并且将top的左右孩子入栈。
(3)如果为空则退出循环。
(4)再检查栈中是否有不为空的元素,没有则是完全二叉树,返回true,否则返回false。
2>实现
//判断当前数是否为完全 二叉树
boolean CompletebinaryTreeNode(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.offer(root);
}
while (!queue.isEmpty()) {
TreeNode top = queue.poll();
if (top != null) {
queue.offer(top.left);
queue.offer(top.right);
} else {
break;
}
}
while (!queue.isEmpty()) {
TreeNode top = queue.peek();
if (top == null) {
queue.poll();
} else {
return false;
}
}
return true;
6.检查两颗树是否相同
1>算法思想
(1)如果两树中有一树为空,一树不为空,则返回false
(2)两树均为空,则返回true;
(3)特殊情况考虑完以后再考虑只要当两个树的相同位置的根的value值不相同时,就不相同,从上到下遍历遍历整棵树。
2>算法实现
public boolean isSameTree(TreeNode p, TreeNode q) {
if ((p != null && q == null) || (p == null && q != null)) {
return false;
}
if (p == null && q == null) {
return true;
}
if (p.value != q.value) {
return false;
}
return isSameTree(p.left, q.left) &&
isSameTree(p.right, q.right);
}
7.判断一个数是否是高度一致的平衡二叉树
此算法比较简单,但是算法的时间复杂度比较高,为O(N^2)
public boolean isBalence(TreeNode root) {
if (root == null) {
return true;
}
int leftHight = getSize(root.left);
int rightHight = getSize(root.right);
return Math.abs(leftHight - rightHight) < 2 &&
isBalence(root.left) &&
isBalence(root.right);
}
```