选择题
- 前序遍历序列与中序遍历序列相同的二叉树为( )。
A. 根结点无左子树的二叉树
B. 根结点无右子树的二叉树
C. 只有根结点的二叉树或非叶子结点只有左子树的二叉树
D. 只有根结点的二叉树或非叶子结点只有右子树的二叉树
【解析】要使前序遍历序列与中序遍历序列相同,对于任意非叶子结点,不能存在左子树,否则前序遍历序列与中序遍历序列不可能相同。除此之外,只有根结点的二叉树,前序、中序、后序遍历都相同。
- 如果根的高度为 1 1 1,具有 61 61 61 个结点的完全二叉树的高度为(
6
)。
【解析】有 n n n个结点完的全二叉树高度 h = ⌊ l o g 2 n ⌋ + 1 h=\lfloor log_2^n \rfloor+1 h=⌊log2n⌋+1,所以答案为 ⌊ l o g 2 61 ⌋ + 1 = 6 \lfloor log_2^{61} \rfloor+1=6 ⌊log261⌋+1=6。
- 设某算法的计算时间表示为递推关系式 T ( n ) = T ( n − 1 ) + n T(n)= T(n-1)+ n T(n)=T(n−1)+n( n n n 为正整数)及 T ( 0 ) = 1 T(0)= 1 T(0)=1,则该算法的时间复杂度为( O ( n 2 ) O(n^2) O(n2) )。
【解析】通过递推式,可以得到: T ( n ) = T ( n − 1 ) + n = T ( n − 2 ) + n − 1 + n = T ( n − 3 ) + n − 2 + n − 1 + n = T ( 0 ) + 1 + 2 + . . . + n T(n)= T(n-1)+ n=T(n-2)+n-1+n=T(n-3)+n-2+n-1+n=T(0) +1+2+...+n T(n)=T(n−1)+n=T(n−2)+n−1+n=T(n−3)+n−2+n−1+n=T(0)+1+2+...+n。
整理后: T ( n ) = 1 + 2 + . . . + n = ( 1 + n ) × n / 2 T(n)=1+2+...+n=(1+n)\times n/2 T(n)=1+2+...+n=(1+n)×n/2,所以该算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
问题求解
- 重新排列 1234 1234 1234 使得每一个数字都不在原来的位置上,一共有(
9
)种排法。
【解析】错排问题。 问题规模较小,也可以手动枚举。错排的方案有:
2143
、2341
、2413
、3142
、3412
、3421
、4123
、4312
、4321
,一共9
种。
解决错排问题的算法思想是将排列第n个数的情况 f ( n ) f(n) f(n)分为两类:
- 前面 n − 1 n-1 n−1个数已经完成错排,那么从前面 n − 1 n-1 n−1个数中任意挑出一个数与第 n n n个数进行交换,此时构成 n n n个数的错排,方案总数为 ( n − 1 ) × f ( n − 1 ) (n-1)\times f(n-1) (n−1)×f(n−1)。
- 前面 n − 1 n-1 n−1个数只有一个数在自己原来位置,即已经构成 n − 2 n-2 n−2个数的错排,此时将该数与第 n n n个数进行交换,则也能构成 n n n个数的错排,方案总数为 ( n − 1 ) × f ( n − 2 ) (n-1)\times f(n-2) (n−1)×f(n−2)。
所以, n n n个数的错排方案总数为: f ( n ) = ( n − 1 ) × ( f ( n − 1 ) + f ( n − 2 ) ) f(n)=(n-1)\times(f(n-1)+f(n-2)) f(n)=(n−1)×(f(n−1)+f(n−2))。
初始状态: f ( 1 ) = 0 , f ( 2 ) = 1 , f ( 3 ) = 2 , f ( 4 ) = 9 f(1)=0, f(2)=1,f(3)=2,f(4)=9 f(1)=0,f(2)=1,f(3)=2,f(4)=9答案:
9
- 一棵结点数为 2015 2015 2015 的二叉树最多有(
1008
)个叶子结点。
【解析】二叉树中结点总数 n = n 0 + n 1 + n 2 n=n_0+n_1+n_2 n=n0+n1+n2。根据二叉树的性质: n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1,要保证二叉树中叶子结点最多,那么 n 1 n_1 n1要尽可能的少,此时的二叉树一定是一棵完全二叉树。根据完全二叉树的性质,最后一个拥有孩子的结点的父结点的编号 = n / 2 =n/2 =n/2,那么一棵结点数为:
2015 2015 2015 的二叉树最多有 2015 − 2015 / 2 = 1008 2015-2015/2=1008 2015−2015/2=1008个叶子结点。
完善程序
- (打印月历)输入月份 m ( 1 ≤ m ≤ 12 ) m(1 \le m \le 12) m(1≤m≤12),按一定格式打印 2015 2015 2015 第 m m m 月的月历。例如,2015 年一月的月历打印效果如下(第一列为周日):
#include<iostream>
using namespace std;
const int dayNum[]={-1,31,28,31,30,31,30,31,31,30,31,30,31};
int m, offset, i;
int main()
{
cin >> m;
cout <<"S M T W T F S"<<endl;//' '为tab制表符
①;
for (i = 1; i < m; i++)
offset = ②;
for (i = 0; i < offset; i++)
cout <<' ';
for (i = 1; i <= ③;i++)
{
cout << ④;
if(i==dayNum[m]||⑤==0)
cout << endl;
else
cout << ' ';
}
return 0;
}
【解析】通过偏移数
offset
将每个月的日期输出到对应的星期上。
空①,offset
记录上个月的偏移数,1月份的偏移数为4
,所以此空应填:offset=4
空②,计算第m
个月的偏移数,所以应加上前一个月的天数并对7取余数,(offset+dayNum[i])%7
空③,输出第m
个月的日期,dayNum[m]
空④,输出循环变量i
表示的日期
空⑤,换行条件,当前日期加上偏移数如果是7的倍数时换行,所以应填入:(offset+i)%7
- (中位数)给定 n n n( n n n 为奇数且小于 1000 1000 1000)个整数,整数的范围在 0 m 0~m 0 m( 0 < m < 2 31 0 \lt m \lt 2^{31} 0<m<231)之间,请使用二分法求这 nn 个整数的中位数。所谓中位数,是指将这 n n n 个数排序之后,排在正中间的数。
#include <iostream>
using namespace std;
const int MAXN = 1000;
int n,i,lbound,rbound,mid,m,count;
int x[MAXN];
int main()
{
cin >> n >> m;
for(i = 0; i < n; i++)
cin >> x[i];
lbound = 0;rbound = m;
while(①) {
mid=(lbound+rbound)/2;
②;
for(i = 0; i < n; i++)
{
if(③)
④;
}
if(count > n/2)
lbound = mid + 1;
else
⑤;
}
cout << rbound << endl;
return 0;
}
【解析】二分搜索求中位数。
lbound
和rbound
即中位数的左右边界。
- 空①,二分搜索的循环条件,即
lbound<rbound
- 空②,
count
记录x[]
中比中位数mid
大的数的个数,此时应该初始化为0
,所以此空应填入count=0
。- 空③,
if(count > n/2) lbound = mid + 1;
表示:如果count
的个数超过了一半,再到更大的值区间中搜索中位数,即mid
不够大。所以此空应填入x[i]>mid
。- 空④,
count++
- 空⑤,
count <= n/2
,到更小的值空间搜索,此时rbound=mid
。