面试题
1. NP问题与P问题:
P类问题:能在多项式时间内可解的问题。
NP问题:在多项式时间内“可验证”的问题。也就是说,不能判定这个问题到底有没有解,而是猜出一个解来,并在多项式时间内证明这个解是否正确。即对其某一个解的验证则能够在多项式时间内完成。
NPC问题:存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。有两个条件:
规约:一个问题规约为另一个问题,时间复杂度增加了,问题的应用范围也增大了。
问题A可以约化为问题B,称为“问题A可规约为问题B”,可以理解为问题B的解一定就是问题A的解,因此解决A不会难于解决B。由此可知问题B的时间复杂度一定大于等于问题A。
- 是一个NP问题
- 所有NP问题都能规约到它
NPH问题:它满足NPC问题定义的第二条但不一定要满足第一条。即所有的NP问题都能约化到它,但NPH问题可以不是NP问题。即使NPC问题发现了多项式级的算法,NP-Hard问题有可能仍然无法得到多项式级的算法。
2.顺序图的构成:
定义:按时间顺序显示对象交互的图。
构成:对象、生命线、激活(控制焦点)和消息。
在UML中,顺序图将交互关系表示为一张二维图。其中纵向是代表时间维度,时间向下延伸,按时间依次列出各个对象所发出和接收的消息。水平方向是代表对象的维度,排列着参与交互的各个独立的对象。
对象:
定义:特定行为和属性的集合。可以细分为:参与者,边界类,控制类,实体类
生命线:
定义:描述对象的存在周期
对象在生命线上两种状态:休眠和激活
激活(控制焦点):
表示一个对象执行一个动作所经历的时间段,既可以是直接执行,也可以是安排下级过程执行。
同时,激活也可以表示对应对象在这段时间内不是空闲的,它正在完成某个任务,或正被占用。
当一个对象没有控制焦点时,该对象处于休眠状态,但是仍然存在,等待新的消息激活
消息:
从一个对象(发送者)向另一个对象(接收者)发送信号,或由一个对象(发送者或调用者)调用另一个对象(接收者)的操作。
消息表示为从一个对象的生命线指向另一个对象的生命线的箭头。
消息的阅读顺序是严格自上而下的。
消息的类型:
同步消息:意味着发出该消息的对象将不再继续进行后续工作,专心等待消息接收方返回消息。
异步消息:消息发出者在发出异步消息之后,不必等待接收者的返回消息便可以继续自己的活动和操作。
3.MySQL 修改表名:
第一种方法:
-- 修改表名, TO 或AS都可以,也以省略掉
-- ALTER TABLE 表名 RENAME [TO|AS] 新表名
ALTER TABLE user10 RENAME TO user11;
第二种方法:
-- 修改表名
-- RENAME TABLE 表名 TO 新表名; 这里面的TO不可以省略
RENAME TABLE user11 TO user10;
4.性能测试的指标:
系统性能测试指标:
- 响应时间
- 并发
- 点击率
- 吞吐量
- TPS:每秒处理的事务数目。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程
- QPS:每秒能处理查询数目。是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。每秒钟处理完请求的次数;QPS = 并发量 / 平均响应时间
- PV:页面浏览量,用户每一次对网站中的每个页面访问均被记录1次。用户对同一页面的多次刷新,访问量累计。
- UV:独立访客,通过客户端的cookies实现。即同一页面,客户端多次点击只计算一次,访问量不累计。
Linux服务器性能指标:
- CPU使用率
- 内存占用率
- 系统平均负载
- 磁盘IO
5.SMART原则:
1. 目标必须是具体的(Specific)
2. 目标必须是可以衡量的(Measurable)
3. 目标必须是可以达到的(AttAInable)
4. 目标必须和岗位职责或战略具有相关性(RelEVAnt)
5. 目标必须具有明确的截止期限(Time-based)
6.Hbase数据库
HBase是一种构建在HDFS之上的分布式、面向列的存储系统。
特点:
- 实时读写、随机访问超大规模数据集
- HBase不是关系型数据库,也不支持SQL
- 稀疏
- 无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列
- 数据类型单一:HBase中的数据都是字符串,没有类型
7.推导与推导二义性:
推导:
二义性:简单来说,就是存在多种推导的过程可以达到所求的句子。
8.SOA的优势:
- 通过互联网服务器发布,从而突破企业内网的限制,实现与供应链上下游伙伴业务的紧密结合
- 与平台无关,减少了业务应用实现的限制
- 具有低耦合性特点,增加和减少业务伙伴对整个业务系统的影响较低
- 具有可按模块分阶段进行实施的优势
- SOA的实施可能并不具有成本显著性。
9.myeclipse的调试
F5——进入:移动到下一个步骤,如果当前行有一个方法调用,该控件将会跳转到被调用方法的第一行执行。
F6——跳出:移动到下一行。如果在当前行有方法调用,那么会直接移动到下一行执行。不会进入被调用方法体里面。
F7——返回:从当前方法中跳出,继续往下执行。
F8——移动到下一个断点处执行。
10.IPV6
长度:128位
回环地址:0:0:0:0:0:0:0:1/128 或者::1/128
压缩0的方法:连续的0 或 前置0
11.URL:统一资源标识符
12.程序设计的基本成分:
程序=数据结构+算法+设计方法+编程工具+语言环境
数据成分,运算成分,控制成分,传输成分。
13.软件测试:
目的:尽可能发现软件中的错误
成功的标志: 发现了至今尚未发现的错误
1.测试的各个阶段
- 单元测试:需要局部数据结构测试,以白盒测试为主
- 系统测试
- 集成测试
- 确认测试
2.黑盒测试、白盒测试
白盒测试:侧重于程序结构
以程序的内部结构为基础
使用的技术:
- 语句覆盖:最弱
- 分支覆盖
- 条件覆盖:使程序中的每个判定中每个条件的可能值至少满足一次。
- 判定-条件覆盖
- 条件组合覆盖:最强
- 路径覆盖
黑盒测试:侧重于功能
例子:因果图
3.Junit测试
适用于在单元测试阶段,进行单个方法实现功能或者类本身的测试。
主要用于白盒测试
4.自动测试
优点:速度快、效率高;准确度和精确度高 ;能提高测试的质量
14. 软件缺陷:
缺陷的定义:
- 缺陷就是软件产品在开发中存在的错误
- 缺陷就是软件维护过程中存在的错误、毛病等各种问题
- 缺陷就是系统所需要实现某种功能的实效和违背
情况:
- 软件没有实现产品规格说明所要求的功能。(少了)
- 软件中出现了产品规格说明不应该出现的功能。(多了)
- 软件实现了产品规格没有提到的功能(多了)
导致缺陷的最大原因:软件需求说明书
15. 贪心、递推、动态规划:
贪心:每个阶段的最优状态都是由上一个阶段的最优状态得到的
定义:每次都选择局部最优,即 每次的最优选择都是在上次的最优选择中得到
缺点:1.不能保证求得的最后解是最佳的
2.不能用来求最大值或最小值的问题
3.只能求满足某些约束条件的可行解的范围
递推:每个阶段只有一个状态,关键是写出递推式
定义:按照一定的规律来计算序列中的每个项,通过计算前面的一些项来得出序列中的指定项的值。
动态规划:关键是找到当前与之前状态的关系
定义:每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到,而不管之前这个状态是如何得到的
例子:求最长上升子序列。
16.系统的设计模式:
1.简单工厂模式:又名静态工厂方法模式,是所有工厂模式中最简单的一个。会定义一个具体的工厂类。
2. 抽象工厂模式:提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。
适用于:一个系统要独立于它的产品的创建、组合和表示;一个系统要由多个产品系列中的一个来配置时;
3.建造者模式:将一个复杂对象的构建与它的表示 分离。
适用于:当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;
当构造过程必须允许被构造的对象有不同的表示
4.工厂方法模式:一个用于创建对象的接口,让子类决定实例化哪一个类,它使一个类的实例化延迟到其子类
适用于:当一个类不知道它所必须创建的对象的类的时候;当一个类希望由它的子类来指定它所创建的对象的时候
当类将创建对象的职责委托给多个子类中的某一个
5.原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
适用于:当一个系统应该独立于它的产品创建、构成和表示时;当要实例化的类是在运行时刻指定时;
6.单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
适用于:当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时;
17.浮点数运算指令:
加减乘除、平方根、正弦、余弦,自然对数、自然整数。
18.编译优化技术:
- 内联函数(方法内联):最重要的优化方法。一是省去方法的调用的成本(查找方法版本、方法入栈、建立栈帧等等),二是为其他的优化建立良好的基础
- 逃逸分析:分析对象的动态作用域:
当一个对象定义在方法内,它可能被外部方法引用,例如作为参数传递到其他方法,这种称为方法逃逸。
甚至会被外部线程访问,这种叫线程逃逸 - 公共子表达式消除::如果一个表达式E之前已经被计算过了,并且从先前的计算到现在E中所有变量的值都没有发生变化**,那么E的这次出现就称为公共子表达式
- 数组边界检查消除
- 冗余访问消除
- 复写传播
- 无用代码的消除
19.内联函数:
使用情况:当函数体较短时,此时函数调用机制所花的时间占据大部分。此时要使用内联函数
定义:编译时在函数调用处直接嵌入函数体,类似于C语言中的宏展开。
使用方法:在函数前加上 inline 关键字。注意要在函数定义处加上,而不是在函数声明处加上
注意:虚函数可以为内联函数,但作为多态的虚函数不能为内联函数。因为内联是在编译时确定,多态是在运行时确定
缺点:会使得代码开销增大,因为会拷贝代码
inline void Print(int x);// 函数声明,无用
inline void Print(int x){// 函数定义
cout<<x<<endl;
}
int main(){
int x=10;
Print(x);
// 在编译时,会将Print(2)变为函数体
cout<<x<<endl;// 会用这句代码替换 Print(x),类似于拷贝
}
不宜使用内联函数的情况:
- 函数体代码长,执行函数的时间较长。这会使得可执行代码膨胀过大
- 函数体内出现循环或者其他复杂的控制结构,那么执行函数体内代码的时间将比函数调用的开销大得多
20. vector
1.vector::erase() 与迭代器
vector::erase有两种重载:
iterator erase(iterator place);删除指定位置,返回下一个元素的迭代器
iterator erase(iterator First, iterator Last); 删除First与Last之间的元素,返回Last之后元素
该函数返回值为迭代器,而传入的迭代器会被释放
2. vector 作为参数
输入参数:vector前要加上 const
void func(const std::vector* pA);
void func(const std::vector& a);
void func(const std::vector*& pA);
void func(const std::vector a);
3.释放vector
要使用 delete []a