问答题
问答题1:对递归程序的优化的一般的手段为?
尾递归是指在函数返回的时候,调用自身本身,并且,return 语句不能包含表达式,这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
尾递归和一般的递归不同点在于对内存的占用,普通递归创建 stack 累积而后计算收缩,尾递归只会占用恒量的内存.
问答题2:将N条长度均为M的有序链表进行合并,合并以后的链表也保持有序,时间复杂度为?
(A) O(N * M * logN)
(B) O(N*M)
(C) O(N)
(D) O(M)
方法一:假设每个有序链表都是升序排列,取出每条链表第一个节点值,一共有N个,则建立大小为N的小堆,这个时间复杂度为O(N),然后新建一个节点作为头结点,取出堆顶元素连在头结点的后面,然后不断的向堆顶加元素一共剩下N(M-1)个元素,每加一次,调整一次,取出堆顶元素连到新建的链表后面,调整一次时间复杂度为O(logN)
所以总共时间复杂度为 O(N) + O(N(M-1)) * O(logN) ,常数阶去掉后得到 O(N * M * logN)
方法二:取出前N个节点进行排序,时间复杂度为O(N * logN),然后剩下的 (M-1)*N 个元素,进行二分查找插入的位置,进行插入.时间复杂度为 O(N * logN) + O((M-1) * N * logN ) = O(M * N * logN)
方法三:数学解题法,令 M = 1,则有N个数字待排序,时间复杂度为O(N*logN) 排除BCD,选择A
问答题3:大小为MAX的循环队列中,f为当前对头元素位置,r为当前队尾元素位置(最后一个元素的位置),则任意时刻,队列中的元素个数为?
A: r-f
B: (r-f+MAX+1)%MAX
C: r-f+1
D: (r-f+MAX)%MAX
提示:如下图,注意题上说的是 rear 指向最后一个元素,而不是最后元素的下一位.
问答题4:n!后面有多少个0,6!=12345*6=720.720后面有1个0,n=10000,求n!
提示:阶乘末尾一个零表示进位,相当于是乘以10,而10=2*5
,所以可以产生10的有以0,2,4,5,6,8结尾的数字。这里2是足够的,关键是5的个数。现在分析:
每个5个,会有一个0,比如5,10,15,20,…
每隔5X5,会多产生一个0,比如25,50,75,…(这里的5只在上一种情况算了一个5,因此在这里加上)
每隔5X5X5游会多出一个5
…
现在算10000的阶乘有几个零:10000/5 + 10000/25 + 10000/125 + 10000/625 + 10000/3125 = 2499
问答题5:若将关键字1,2,3,4,5,6,7 依次插入到初始为空的平衡二叉树 T 中,则 T 中平衡因子为 0 的分支结点的个数是?
提示:4 ,2,6 三个节点的平衡因子为0
平衡二叉树如何移动?
参考:https://blog.csdn.net/qq_43763344/article/details/99118481
问答题6:已知某个哈希表的n个关键字具有相同的哈希值,如果使用二次探测再散列法将这n个关键字存入哈希表,至少要进行几次探测?
提示:问的是至少,那么可以设原表为空,且空间足够大,第一个值,只需一次线性探测,第二个需要两次,第三个需要三次,依次类推,第n个需要n次线性探测,所以总共至少是 n*(n+1)/2 次线性探测
问答题7:下列选项中,不可能是快速排序第2趟排序结果的是?
A: 2,3,5,4,6,7,9
B: 2,7,5,6,4,3,9
C: 3,2,5,4,7,6,9
D: 4,2,3,5,7,6,9
提示:快速排序,即每趟选择某一关键字X,使所有比X大的移到X右边,比X小的移到X左边,若进行两趟快速排序,则至少能找出两个关键字在正确的位置.正确的位置是 2,3,4,5,6,7,9 只有C 不满足要求
编程题
编程题1:小易的升级之路
小易经常沉迷于网络游戏.有一次,他在玩一个打怪升级的游戏,他的角色的初始能力值为 a , 在接下来的一段时间内,他将会依次遇见 n 个怪物,每个怪物的防御力为 b1, b2 , b3…bn. 如果遇到的怪物防御力 bi 小于等于小易的当前能力值 c , 那么他就能轻松打败怪物,并且使得自己的能力值增加 bi ; 如果 bi 大于 c , 那他也能打败怪物,但他的能力值只能增加 bi 与 c 的最大公约数.那么问题来了,在一系列的锻炼后,小易的最终能力值为多少?
输入描述
第一行是两个整数 n 表示怪物的数量和 a 表示小易的初始能力值
第二行 n 个整数,b1,b2…bn 表示每个怪物的防御力
输出描述
对于每组数据,输出一行.每行仅包含一个整数,表示小易的最终能力值
示例:
输入:3 50
50 105 200
输出:110
int GCD(int a, int b){
int c;
while (c = a % b){
a = b;
b = c;
}
return b;
}
int main(){
int n, power;
vector<int> num;
while (cin >> n >> power){
num.resize(n);
for (int i = 0; i < n; i++) {
cin >> num[i];
}
for (int k = 0; k < n; k++){
if (num[k] < power){
power += num[k];
}else{
power += GCD(power, num[k]);
}
}
cout << power << endl;
}
return 0;
}
编程题2:找出字符串中第一个只出现一次的字符
输入描述:输入一个非空字符串
输出描述:输出第一个只出现一次的字符,如果不存在输出 -1
示例1:输入:asdfasdfo 输出:o
int main(){
string s;
while (cin >> s){
//数组内部要指定下标
int hashtable[256] = { 0 };
for (auto& e : s){
hashtable[e]++;
}
int i;
for (i = 0; i < s.size(); i++){
if (hashtable[s[i]] == 1){
cout << s[i] << endl;
break;
}
}
if (i >= s.size())
cout << -1 << endl;
}
return 0;
}