选择题
解析:内联函数是直接替换,没有函数栈帧的销毁,他往往使用在函数中没有循环和递归、代码较少的情况下,同时要求结构不能太复杂。
解析:重载函数的定义:在同一个作用域内,函数名相同,函数参数的类型或者函数参数个数不相同;函数重载和函数返回值没有关系。
解析:a构造了1次,b构造了一次,c构造了3次,AB *p[2]是一个指针数组,数组里面都是指针类型,并没有生成类。
解析:如果用户在类中没有显示定义赋值运算符重载时,编译器自动生成一份——按照浅拷贝方式实现的;
赋值运算符只能作为类的成员函数重载,如果重载成普通的成员函数编译器会报错,编译无法通过;
默认的赋值运算符是编译器自动生成的,按照浅拷贝实现;
重载的赋值构造只有一个形参,因为在参数中前面有一个隐藏的this;
拷贝构造和赋值运算符的重载是两个不同的函数;
解析:静态的成员不能在类的内部初始化,必须在全局进行初始化;
静态成员受访问限定符的限制;
静态成员为该类所有对象共有的,在访问限定符为
public
的情况下可以直接由类名直接访问,也可以由对象进行访问,一般更推荐类名+作用域访问。
解析:ad是一个数组指针,该指针指向一个PAT类型的数组,有3个连续的空间,并没有实例化出对象,所以不会调用构造函数。
解析:当我们没有自己实现析构函数的时候,系统会自动生成默认的析构函数,析构函数是没有参数的。
解析:该程序是没有错误的,
myClass *a = new myClass();
这里的小括号是用来初始化的,显然它用的是默认值,a->foo();
这个也没有错误,会调用foo()
进行释放动态开辟的空间。delete this 代表把当前对象销毁掉
func里面为a new新空间,然后用a指向foo,然后将a对象销毁掉。
解析:构造函数可以有形参,但是析构函数没有形参,不管是析构还是构造函数都没有任何的函数类型。
解析:fun在实例化时,其传递的两个参数的类型必须要一致,如果不一致的话需要显示实例化。
对于模板,都是一个类型的
T
,当没有显示的实例化的时候,该函数的实参的类型必须相同,要不然模板在实例化的时候类型会错误,就不能进行模板的实例化。当显示的说明模板参数类型的时候,就已经实例化了,比如D选项。
编程题
1.最近公共祖先
本人思路:错误。
class LCA { public: int getLCA(int a, int b) { // write code here int parent1 = a / 2; int parent2 = b / 2; if(parent1 == parent2) return parent1; return getLCA(parent1, parent2); } };
解析:当两个数都是子节点时,可以通过找父节点的方式去找公共祖先,但是要考虑当其中一个节点就是他们的公共祖先的情况。
下面代码的思路就是先找到较大节点,再找他的父节点,通过比较得到他们的公共祖先。
/*
满二叉树 parent = child / 2
1
2 3
4 5 6 7
较大的数找父节点,两个数相等时,就是公共祖先
*/
class LCA {
public:
int getLCA(int a, int b) {
while(a != b){
if(a > b) // 让大的数除2就是parent
a /= 2;
else
b /= 2;
}
return a;
}
};
2.求最大连续bit数
解析:
方式一:连除法
思路:将十进制转换成二进制,每次取模得到的是二进制位中最后一个的位数值,如果取模为1,
count++
;取模为0的话说明当前二进制位上的数为0,要开始重新对count
进行计算,和max_count
进行比较,选出最大的。复杂度分析:
- 时间复杂度:
O(log2^n)
,连除取余一共log2^n
次- 空间复杂度:
O(1)
,无额外空间
max
函数,是<algorithm>
中的函数,用来比较大小。
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
int max_count = 0;
int count = 0;
while (n) {
if (n % 2 == 1) { //计算得到的是最后一位
count++;
} else { //当最后一位不等于1时,和上次比较同时将count置0
/*if (count > max) {
max = count;
}*/
max_count = max(count,max_count);
count = 0;
}
n /= 2;
}
/*if (count > max) {
max = count;
}*/
max_count = max(count,max_count);
cout << max_count;
}
方式二:
思路:这道题考察位运算
根据位运算,获取每一位的二进制值。获取第i位的值: (n >> i) & 1。如果1连续,则计数累加,如果不连续,则从0开始计数。
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int n = 0;
cin >> n;
int count = 0;
int max_count = 0;
for(int i = 0; i < 32; i++)
{
if(n & (1 << i))
{
count++;
}
else {
max_count = max(count,max_count);
count = 0;
}
}
cout << max_count;
return 0;
}
方式三:
思路:当一个数和自己左移一位进行位与运算,相当于和自己错开一位进行的位与运算,如果有连续的1,经过错位位与之后会少一个1,如果没有连续的1,错位位与之后就是0。那么我们可以通过这种不断与自己的左移一位位与,直到为0,什么时候结束就说明最大有多少连续的1。
#include<iostream>
using namespace std;
int main(){
int n;
while(cin >> n){
int count = 0;
for(; n != 0; count++) //统计能够运算多少次
n &= n << 1; //与自己左移一位后比较
cout << count << endl;
}
return 0;
}
//
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int count = 0;
while(n)
{
n = (n<<1)&n;
count++;
}
cout << count;
}