re: 全面整理的C++面试题 chatler 2009-12-13 00:39
4。分析一下
#include<iostream.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef struct AA
{
int b1:5;
int b2:2;
}AA;
void main()
{
AA aa;
char cc[100];
strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
memcpy(&aa,cc,sizeof(AA));
cout << aa.b1 <<endl;
cout << aa.b2 <<endl;
}
答案: -16和1
首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
经过strcpy和memcpy后,aa的4个字节所存放的值是:
0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
所以,最后一步:显示的是这4个字节的前5位,和之后的2位
分别为:10000,和01
因为int是有正负之分 所以是-16和1
5。求函数返回值,输入x=9999;
int func ( x )
{
int countx = 0;
while ( x )
{
countx ++;
x = x&(x-1);
}
return countx;
}
结果呢?
答案:知道了这是统计9999的二进制数值中有多少个1的函数,且有
9999=9×1024+512+256+15
9×1024中含有1的个数为2;
512中含有1的个数为1;
256中含有1的个数为1;
15中含有1的个数为4;
故共有1的个数为8,结果为8。
1000 - 1 = 0111,正好是原数取反。这就是原理。
用这种方法来求1的个数是很效率很高的。
不必去一个一个地移位。循环次数最少。
6。int a,b,c 请写函数实现C=a+b ,不可以改变数据类型,如将c改为long int,关键是如何处理溢出问题
答案:bool add (int a, int b,int *c)
{
*c=a+b;
return (a>0 && b>0 &&(*c
a || *c>b)));
}
这里,第三个或条件没看明白,觉得逻辑上出现不了啊。
7。分析:
struct bit
{ int a:3;
int b:2;
int c:3;
};
int main()
{
bit s;
char *c=(char*)&s;
cout< *c=0x99;
cout << s.a < int a=-1;
printf("%x",a);
return 0;
}
输出为什么是?
答案:4
1
-1
-4
ffffffff
因为0x99在内存中表示为 100 11 001 , a = 001, b = 11, c = 100(在vc环境中,一般是由右到左进行分配的)
当c为有符合数时, c = 100, 最高1为表示c为负数,负数在计算机用补码表示,所以c = -4;同理
b = -1;
当c为有符合数时, c = 100,即 c = 4,同理 b = 3
8。改错:
#include
int main(void) {
int **p;
int arr[100];
p = &arr;
return 0;
}
答案:搞错了,是指针类型不同,
int **p; //二级指针
&arr; //得到的是指向第一维为100的数组的指针
应该这样写#include
int main(void) {
int **p, *q;
int arr[100];
q = arr;
p = &q;
return 0;
9。下面这个程序执行后会有什么错误或者效果:
#define MAX 255
int main()
{
unsigned char A[MAX],i; //i被定义为unsigned char
for (i=0;i<=MAX;i++)
A[i]=i;
}
答案:死循环加数组越界访问(C/C++不进行数组越界检查)
MAX=255
数组A的下标范围为:0..MAX-1,这是其一..
其二.当i循环到255时,循环内执行:
A[255]=255;
这句本身没有问题..但是返回for (i=0;i<=MAX;i++)语句时,
由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去.
11。struct name1{
char str;
short x;
int num;
}
struct name2{
char str;
int num;
short x;
}
sizeof(struct name1)=??,sizeof(struct name2)=??
答案:sizeof(struct name1)=8,sizeof(struct name2)=12
在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。
re: 微软面试中简单的算法题目(转) chatler 2009-12-06 23:33
1.烧一根不均匀的绳子,从头烧到尾总共需要 1 个小时,问如何用烧绳子
的方法来确定半小时的时间呢?
2.10 个海盗抢到了100 颗宝石,每一颗都一样大小且价值连城。他们决定
这么分:
(1)抽签决定自己的号码(1~10);
(2)首先,由1 号提出分配方案,然后大家表决,当且仅当超过半数的人
同意时,按照他的方案进行分配,否则将被扔进大海喂鲨鱼;
(3)如果1 号死后,再由2 号提出分配方案,然后剩下的4 个人进行表决,
当且仅当超过半数的人同意时,按照他的方案进行分配,否则将被扔入大海喂鲨
鱼;
(4)依此类推??
条件:每个海盗都是很聪明的人,都能很理智地做出判断,从而做出选择。
问题:第一个海盗提出怎样的分配方案才能使自己的收益最大化?
3.为什么下水道的盖子是圆的?
4.中国有多少辆汽车?
5.你让工人为你工作7 天,回报是一根金条,这根金条平分成相连的7 段,
你必须在每天结束的时候给他们一段金条。如果只允许你两次把金条弄断,你如
何给你的工人付费?
6.有一辆火车以每小时15 公里的速度离开北京直奔广州,同时另一辆火车
以每小时20 公里的速度从广州开往北京。如果有一只鸟,以30 公里每小时的速
度和两辆火车同时启动,从北京出发,碰到另一辆车后就向相反的方向返回去飞,
就这样依次在两辆火车之间来回地飞,直到两辆火车相遇。请问,这只鸟共飞行
了多长的距离?
7.你有两个罐子以及50 个红色弹球和50 个蓝色弹球,随机选出一个罐子,
随机选出一个弹球放入罐子,怎样给出红色弹球最大的选中机会?在你的计划
里,得到红球的几率是多少?
8.想像你站在镜子前,请问,为什么镜子中的影像可以左右颠倒,却不能
上下颠倒呢?
9.如果你有无穷多的水,一个3 公升的提捅,一个5 公升的提捅,两只提
捅形状上下都不均匀,问你如何才能准确称出4 公升的水?
10.你有一桶果冻,其中有黄色、绿色、红色三种,闭上眼睛抓取同种颜色
的两个。抓取多少次就可以确定你肯定有两个同一颜色的果冻?
11.连续整数之和为1000 的共有几组?
12.从同一地点出发的相同型号的飞机,可是每架飞机装满油只能绕地球飞
半周,飞机之间可以加油,加完油的飞机必须回到起点。问至少要多少架次,才
能满足有一架绕地球一周。
参考答案:
1.两边一起烧。
2.96,0,1,0,1,0,1,0,1,0。
3.因为口是圆的。
4.很多。
5.分1,2,4。
6.6/7 北京到广州的距离。
7.100%。
8.平面镜成像原理(或者是“眼睛是左右长的”)。
9.3 先装满,倒在5 里,再把3 装满,倒进5 里。把5 里的水倒掉,把3 里
剩下的水倒进5 里,再把3 装满,倒进5 里,ok!
10.一次。
11.首先1000 为一个解。连续数的平均值设为x,1000 必须是x 的整数倍。
假如连续数的个数为偶数个,x 就不是整数了。x 的2 倍只能是5,25,125 才行。
因为平均值为12.5,要连续80 个达不到。125/2=62.5 是可以的。即62,63,61,
64,等等。连续数的个数为奇数时,平均值为整数。1000 为平均值的奇数倍。
1000=2×2×2×5×5×5;x 可以为2,4,8,40,200 排除后剩下40 和200 是
可以的。所以答案为平均值为62.5,40,200,1000 的4 组整数。
12.答案是5 架次。一般的解法可以分为如下两个部分:
(1)直线飞行
一架飞机载满油飞行距离为1,n 架飞机最远能飞多远?在不是兜圈没有迎
头接应的情况,这问题就是n 架飞机能飞多远?存在的极值问题是不要重复飞
行,比如两架飞机同时给一架飞机加油且同时飞回来即可认为是重复,或者换句
话说,离出发点越远,在飞的飞机就越少,这个极值条件是显然的,因为n 架飞
机带的油是一定的,如重复,则浪费的油就越多。比如最后肯定是只有一架飞机
全程飞行,注意“全程”这两个字,也就是不要重复的极值条件。如果是两架飞
机的话,肯定是一架给另一架加满油,并使剩下的油刚好能回去,就说第二架飞
机带的油耗在3 倍于从出发到加油的路程上,有三架飞机第三架带的油耗在5
倍于从出发到其加油的路程上,所以n 架飞机最远能飞行的距离为s=1+1/3+?
+1/(2n+1)这个级数是发散的,所以理论上只要飞机足够多最终可以使一架飞
机飞到无穷远,当然实际上不可能一架飞机在飞行1/(2n+1)时间内同时给n?1
个飞机加油。
(2)可以迎头接应加油
一架飞机载满油飞行距离为1/2,最少几架飞机能飞行距离1?也是根据不
要重复飞行的极值条件,得出最远处肯定是只有一架飞机飞行,这样得出由1/2
处对称两边1/4 肯定是一架飞机飞行,用上面的公式即可知道一边至少需要两架
飞机支持,(1/3+1/5)/2>1/4(左边除以2 是一架飞机飞行距离为1/2),但
是有一点点剩余,所以想像为一个滑轮(中间一个飞机是个绳子,两边两架飞机
是个棒)的话,可以滑动一点距离,就说加油地点可以在一定距离内变动(很容
易算出来每架飞机的加油地点和加油数量,等等)
每个IE Instance该是不同的进程吧,可以获取进程ID,在每个instance里建一个名称包含进程id的目录名,就可以分目录存储了吧。
re: 一个关于单向链表的面试题 chatler 2008-09-14 23:42
还有一种算法,就是用有向图来实现(具体见下面代码):
把链表看成一个有向图,深度优先遍历该有向图,判断有无循环出现。
懒得再用中文写一遍具体算法了,看下面的代码实现吧,英文注释解释的很清楚了。
时间复杂度 O(e), 链表边的总数。
空间复杂度 O(1).
有向图采用邻接表实现。
/* file: DFSDetectLoop.cpp */
/*
* Detect if the graph has loop -- For both Undigraph and digraph
* Complexity: O(e); e is the number of arcs in Graph.
*
* BUG Reported:
* 1. Apr-26-07
* Not support Undigraph yet ! Fix me !!!
* - Fixed on Apr-26-08.
*
* Return
* 1 - Loop detected.
* 0 - No loop detected.
* *
* Algrithm:
* 1. Init all the nodes color to WHITE.
* 2. DFS graph
* For each the nodes v in graph, do step (1) and (2).
* (1) If v is WHITE, DFS from node v:
* (a) Mark v as GRAY.
* (b) For every nodes tv adjacent with node v,
* (i) If the current visiting node is gray, then loop detected. exit.
* (ii) Goto Step (1).
* (iii) All the nodes on sub-tree of tv have been visited. Mark node tv as BLACK.
* (2) All the nodes on sub-tree of v have been visited. Mark node v as BLACK.
*
* Function DFSDetectLoop is valid for both Undigraph and digraph.
*
* */
int DFSDetectLoop (ALGraph *graph, int VisitFunc (ALGraph *graph, int v))
{
int v;
for (v = 0; v < graph->vexnum; v++)
{
MarkNodeColor (graph, v, WHITE);
}
for (v = 0; v < graph->vexnum; v++)
{
if (graph->vertices[v].color == WHITE)
{
/* We are good to call DFSDetectLoopSub the first
* time with pv = -1, because no node equals -1.
* */
if (1 == DFSDetectLoopSub (graph, v, -1, VisitFunc))
return 1;
}
MarkNodeColor (graph, v, BLACK);
}
return 1;
}
/*
* Start from node v, DFS graph to detect loop.
* pv is the node that just visited v. pv is used to avoid v to visit pv again.
* pv is introduced to support Undigraph.
*
* NOTE:
* Before calling DFSDetectLoopSub, make sure node v is not visited yet.
* */
int DFSDetectLoopSub (ALGraph *graph, int v, int pv, int VisitFunc (ALGraph *graph, int v))
{
assert (graph->vertices[v].color == WHITE);
MarkNodeColor (graph, v, GRAY);
VisitFunc (graph, v);
ArcNode *arc;
arc = graph->vertices[v].firstarc;
while (arc)
{
int tv = arc->adjvex;
/* For Undigraph, if tv equals pv, this arc should not be count.
* Because we have just visited from pv to v.
* Just go ahead to check next vertex connected with v.
* 1----2, after visit 1, we will visit 2, while visiting 2, 1 will be the 1st node visited.
*
* For digraph, we need to check loop even tv equals pv.
* Because there is case that node v points to u, and u points to v.
* */
if ((graph->kind == AG) && (tv != pv))
{
if ( graph->vertices[tv].color == GRAY )
{
cout << "Gray node visited at node: " << tv + 1 <<endl;
cout << "DFSDetectLoopSub: Loop Detected at from node " << v + 1<<" to "<< tv + 1 <<" !" <<endl;
return 1;
}
if (graph->vertices[tv].color == WHITE)
{
if (1 == DFSDetectLoopSub (graph, tv, v, VisitFunc))
{
return 1;
}
}
/* At this line:
* (1)If tv's color is already BLACK; Go ahead checking next arc;
* (2)If the sub-tree of node tv has all been visited, mark as BLACK and check next arc;
* Backward tv to to v's other adjacent node. So tv should be marked as black.
* */
MarkNodeColor (graph, tv, BLACK);
}
arc = arc->nextarc;
}
return 0;
}