一、选择题
1、一棵有15个节点的完全二叉树和一棵同样有15个节点的普通二叉树,叶子节点的个数最多会差多少个?(C)
A. 3
B. 5
C. 7
D. 9
答案解析:C
根据满二叉树的计算公式:20+21+…+2^(n-1)
有15个结点的完全二叉树总共有4层,第四层是叶子结点,总共有8个叶子结点;
有15个结点的普通二叉树最少有1个叶子结点(单边二叉树),所以差值为7;
2、在一棵二叉树中,假定每个结点只有左孩子,没有右孩子,对它分别进行前序遍历和后序遍历,则具有相同的遍历结果。(B )
A. 正确
B. 错误
答案解析:B
前序遍历是先访问根节点,再访问左子树,最后访问右子树;
后序遍历是先访问左子树,再访问右子树,最后才访问根节点;
根据题意设一棵二叉树只有两个结点,根节点为A,左子树为B,前序遍历为AB,后序遍历为BA,所以这句话错误
3、一棵满二叉树同时又是一棵平衡树。这种说法(A )
A. 正确
B. 错误
答案解析:A
平衡二叉树性质:左子树和右子树都是平衡二叉树;每一个节点的左右子树高度差的绝地值 <= 1
满二叉树每一个结点的高度差都为0,所以满二叉树是平衡二叉树
4、已知一棵二叉树的先序和中序遍历序列如下:先序:A、B、C、D、E、F、G、H、I,J中序:C、B、A、E、F、D、I、H、J、G其后序遍历序列为(E )
A. C、B、D、E、A、G、I、H、J、F
B. C、B、D、A、E、G、I、H、J、F
C. C、E、D、B、I、J、H、G、F、A
D. C、E、D、B、I、H、J、G、F、A
E. C、B、F、E、I、J、H、G、D、A
答案解析:E
后序遍历是先左子树,后右子树,最后根节点
由先序遍历知道,A是根节点,排除 A B选项
由中序遍历知道,A的左子树只有两个结点C,B,排除C D 选项;
5、完全二叉树中的叶子结点只可能在最后两层中出现 (A )
A. 正确
B. 错误
答案解析:A
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中
编号从1至n的结点一一对应时称之为完全二叉树。
所以叶子节点只能出现在最后两层,不然就不符合完全二叉树的定义的。
二、编程题
1、最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
OJ链接
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
【解题思路】:
对于栈来说,如果一个元素 a 在入栈时,栈里有其它的元素 b, c, d,那么无论这个栈在之后经历了什么操作,只要 a在栈中,b, c, d 就一定在栈中,因为在 a 被弹出之前,b, c, d 不会被弹出。因此,在操作过程中的任意一个时刻,只要栈顶的元素是 a,那么我们就可以确定栈里面现在的元素一定是 a, b, c, d。那么,我们可以在每个元素 a 入栈时把当前栈的最小值 m 存储起来。在这之后无论何时,如果栈顶元素是 a,我们就可以直接返回存储的最小值 m。
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minstack;
public MinStack() {
stack=new Stack<>();
minstack=new Stack<>();
}
public void push(int val) {
stack.push(val);
if(!minstack.empty()){
int top=minstack.peek();
//比较小于等于放进去
if(val<=top){
minstack.push(val);
}
}else{
minstack.push(val);
}
}
public void pop() {
int popval=stack.pop();
if(!minstack.empty()){
int top=minstack.peek();
if(top==popval){
minstack.pop();
}
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minstack.peek();
}
}
2、有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
OJ链接
示例1:
输入:s = "()"
输出:true
示例2:
输入:s = "()[]{}"
输出:true
示例3:
输入:s = "([)]"
输出:false
【解题思路】:
碰到左括号就入栈,碰到右括号就出栈顶元素查看是否匹配,有一个反例返回false;最终遍历结束栈不为空返回false,否则返回true。
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length();i++) {
char ch = s.charAt(i);
if(ch == '(' || ch == '[' || ch == '{') {
//如果是左括号 直接入栈
stack.push(ch);
}else{
//遇到了右括号
if(stack.empty()) {
//右括号多
return false;
}
char top = stack.peek();//哪个左括号
if(top == '{' && ch == '}' || top == '[' && ch == ']' || top == '(' && ch == ')') {
stack.pop();
}else{
//左右括号不匹配
return false;
}
}
}
if(!stack.empty()) {
//左括号多
return false;
}
return true;
}
}