中间二十试题加答案.docx
- 文档编号:26021783
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:49
- 大小:38.87KB
中间二十试题加答案.docx
《中间二十试题加答案.docx》由会员分享,可在线阅读,更多相关《中间二十试题加答案.docx(49页珍藏版)》请在冰豆网上搜索。
中间二十试题加答案
永久勘误:
微软等面试100题系列,答案V0.3版[第21-40题答案]
第21题
2010年中兴面试题
编程求解:
输入两个整数n和m,从数列1,2,3.......n中随意取几个数,
使其和等于m,要求将其中所有的可能组合列出来.
//此题与第14题差不多,在次不做过多解释。
//July、2010/10/22。
本程序,经网友指出有误,但暂时没有想到解决的办法。
见谅。
#include
#include
usingnamespacestd;
voidqiujie(intsum,intn)
{
staticlist
if(n<1||sum<1)
return;
if(sum>n)
{
ilist.push_front(n);
qiujie(sum-n,n-1);
ilist.pop_front();
qiujie(sum,n-1);
}
else
{
cout< for(list : iteratorit=ilist.begin();it! =ilist.end();++it) cout<<""<<*it; cout< } } intmain() { intm,n; cout<<"请输入你要等于多少的数值m: "< cin>>m; cout<<"请输入你要从1.....n数列中取值的n: "< cin>>n; qiujie(m,n); return0; } /////////////////////////////////////////// 请输入你要等于多少的数值m: 10 请输入你要从1.....n数列中取值的n: 8 28 37 46 145 235 1234 Pressanykeytocontinue /////////////////////////////////////// 第22题: 有4张红色的牌和4张蓝色的牌,主持人先拿任意两张, 再分别在A、B、C三人额头上贴任意两张牌, A、B、C三人都可以看见其余两人额头上的牌, 看完后让他们猜自己额头上是什么颜色的牌, A说不知道,B说不知道,C说不知道,然后A说知道了。 请教如何推理,A是怎么知道的。 如果用程序,又怎么实现呢? //July、2010/10/22 //今是老妈生日,祝福老妈,生日快乐。 ! : ). 4张r4张b 有以下3种组合: rrbbrb 1.B,C全是一种颜色 BCA bb.rrbb.rr 2. BCA bbrrbb/RR/BR,=>A: BR rrbb=>A: BR 3. BCA BRBBRR/BR,=>A: BR //推出A: BR的原因, //如果A是RR, //那么,当ABC都说不知道后,B最后应该知道自己是BR了。 //因为B不可能是RR或BB。 4. BCA BRBRBB/RR/BR //推出A: BR的原因 //如果,A是BB,那么B=>BR/RR, //如果B=>RR,那么一开始,C就该知道自己是BR了。 //如果B=>BR, //最后,也还是推出=>A: BR //至于程序,暂等高人。 第24题: 1.反转链表 2.合并链表。 [合并链表的答案,请参考第42题] pPrev<-pNode<-pNext ListNode*ReverseIteratively(ListNode*pHead) { ListNode*pReversedHead=NULL; ListNode*pNode=pHead; ListNode*pPrev=NULL; while(pNode! =NULL)//pNode<=>m { ListNode*pNext=pNode->m_pNext;//n保存在pNext下 //如果pNext指为空,则当前结点pNode设为头。 if(pNext==NULL) pReversedHead=pNode; //reversethelinkagebetweennodes pNode->m_pNext=pPrev; //moveforwardonthethelist pPrev=pNode; pNode=pNext; } returnpReversedHead; } 或者,这样写: head->next->p->q template Node { p=head->next; while(p) { q=p->next;//p->next先保存在q下 p->next=head->next;//p掉头指向head->next head->next=p;//p赋给head->next p=q;//q赋给p。 //上俩行即,指针前移嘛... } returnhead; 第25题: 写一个函数,它的原形是intcontinumax(char*outputstr,char*intputstr) 功能: 在字符串中找出连续最长的数字串,并把这个串的长度返回, 并把这个最长数字串付给其中一个函数参数outputstr所指内存。 例如: "abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9, outputstr所指的值为123456789 //leeyunce 这个相对比较简单,思路不用多说,跟在序列中求最小值差不多。 未经测试。 有错误欢迎指出。 intcontinumax(char*outputstr,char*intputstr) { inti,maxlen=0; char*maxstr=0; while(true) { while(intputstr&&(*intputstr<'0'||*intputstr>'9'))//skipallnon-digit characters { intputstr++; } if(! intputstr)break; intcount=0; char*tempstr=intputstr; while(intputstr&&(*intputstr>='0'&&*intputstr<='9'))//OK,thesecharactersare digits { count++; intputstr++; } if(count>maxlen) { maxlen=count; maxstr=tempstr; } } for(i=0;i { outputstr[i]=maxstr[i]; } outputstr[i]=0; returnmaxlen; } 26.左旋转字符串 题目: 定义字符串的左旋转操作: 把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。 请实现字符串左旋转的函数。 要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O (1)。 分析: 如果不考虑时间和空间复杂度的限制, 最简单的方法莫过于把这道题看成是把字符串分成前后两部分, 通过旋转操作把这两个部分交换位置。 于是我们可以新开辟一块长度为n+1的辅助空间, 把原字符串后半部分拷贝到新空间的前半部分,在把原字符串的前半部分拷贝到新空间的后半部分。 不难看出,这种思路的时间复杂度是O(n),需要的辅助空间也是O(n)。 把字符串看成有两段组成的,记位XY。 左旋转相当于要把字符串XY变成YX。 我们先在字符串上定义一种翻转的操作,就是翻转字符串中字符的先后顺序。 把X翻转后记为XT。 显然有 (XT)T=X。 我们首先对X和Y两段分别进行翻转操作,这样就能得到XTYT。 接着再对XTYT进行翻转操作,得到(XTYT)T=(YT)T(XT)T=YX。 正好是我们期待的结果。 分析到这里我们再回到原来的题目。 我们要做的仅仅是把字符串分成两段, 第一段为前面m个字符,其余的字符分到第二段。 再定义一个翻转字符串的函数,按照前面的步骤翻转三次就行了。 时间复杂度和空间复杂度都合乎要求。 #include"string.h" //Movethefirstncharsinastringtoitsend char*LeftRotateString(char*pStr,unsignedintn) { if(pStr! =NULL) { intnLength=static_cast if(nLength>0||n==0||n>nLength) { char*pFirstStart=pStr; char*pFirstEnd=pStr+n-1; char*pSecondStart=pStr+n; char*pSecondEnd=pStr+nLength-1; //reversethefirstpartofthestring ReverseString(pFirstStart,pFirstEnd); //reversethesecondpartofthestrint ReverseString(pSecondStart,pSecondEnd); //reversethewholestring ReverseString(pFirstStart,pSecondEnd); } } returnpStr; } //ReversethestringbetweenpStartandpEnd voidReverseString(char*pStart,char*pEnd) { if(pStart==NULL||pEnd==NULL) { while(pStart<=pEnd) { chartemp=*pStart; *pStart=*pEnd; *pEnd=temp; pStart++; pEnd--; } } } ======================== 针对262楼litaoye的回复: 26.左旋转字符串 跟panda所想,是一样的,即, 以abcdef为例 1.ab->ba 2.cdef->fedc 原字符串变为bafedc 3.整个翻转: cdefab //时间复杂度为O(n) 在此,奉献另外一种思路: abcdefghi,要abc移动至最后 abcdefghi->defabcghi->defghiabc 一俩指针,p1指向ch[0],p2指向[chm-1], p2每次移动m的距离,p1也跟着相应移动, 每次移动过后,交换。 如上第一步,交换abc和def,就变成了abcdef->defabc 第一步, abcdefghi->defabcghi 第二步,继续交换, defabcghi->defghiabc 整个过程,看起来,就是abc一步一步向后移动 abcdefghi defabcghi defghiabc //最后的复杂度是O(m+n) 再举一个例子, 如果1234567890要变成4567890123: 1234567890 1.4561237890 2.4567891230 3.4567891203 4.4567891023 5.4567890123//最后三步,相当于0前移,p1已经不动。 欢迎,就此第26题,继续讨论。 二零一一年一月十七日补正。 ============================================= 27.跳台阶问题 题目: 一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。 求总共有多少总跳法,并分析算法的时间复杂度。 首先我们考虑最简单的情况。 如果只有1级台阶,那显然只有一种跳法。 如果有2级台阶,那就有两种跳的方法了: 一种是分两次跳,每次跳1级;另外一种就是一次跳2级。 现在我们再来讨论一般情况。 我们把n级台阶时的跳法看成是n的函数,记为f(n)。 当n>2时,第一次跳的时候就有两种不同的选择: 一是第一次只跳1级, 此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1); 另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳法数目,即为f(n-2)。 因此n级台阶时的不同跳法的总数f(n)=f(n-1)+(f-2)。 我们把上面的分析用一个公式总结如下: /1n=1 f(n)=2n=2 \f(n-1)+(f-2)n>2 分析到这里,相信很多人都能看出这就是我们熟悉的Fibonacci序列。 intjump_sum(intn)//递归版本 { assert(n>0); if(n==1||n==2)returnn; returnjump_sum(n-1)+jump_sum(n-2); } intjump_sum(intn)//迭代版本 { assert(n>0); if(n==1||n==2)returnn; intan,an_1=2,an_2=1; for(;n>=3;n--) { an=an_2+an_1; an_2=an_1; an_1=an; } returnan; } 28.整数的二进制表示中1的个数 题目: 输入一个整数,求该整数的二进制表达中有多少个1。 例如输入10,由于其二进制表示为1010,有两个1,因此输出2。 分析: 这是一道很基本的考查位运算的面试题。 包括微软在内的…… 一个很基本的想法是,我们先判断整数的最右边一位是不是1。 接着把整数右移一位,原来处于右边第二位的数字现在被移到第一位了, 再判断是不是1。 这样每次移动一位,直到这个整数变成0为止。 现在的问题变成怎样判断一个整数的最右边一位是不是1了。 很简单,如果它和整数1作与运算。 由于1除了最右边一位以外,其他所有位都为0。 因此如果与运算的结果为1,表示整数的最右边一位是1,否则是0。 */ 得到的代码如下: /////////////////////////////////////////////////////////////////////// //Gethowmany1sinaninteger'sbinaryexpression /////////////////////////////////////////////////////////////////////// intNumberOf1_Solution1(inti) { intcount=0; while(i) { if(i&1) count++; i=i>>1; } returncount; } 可能有读者会问,整数右移一位在数学上是和除以2是等价的。 那可不可以把上面的代码中的右移运算符换成除以2呢? 答案是最好不要换成除法。 因为除法的效率比移位运算要低的多, 在实际编程中如果可以应尽可能地用移位运算符代替乘除法。 这个思路当输入i是正数时没有问题,但当输入的i是一个负数时, 不但不能得到正确的1的个数,还将导致死循环。 以负数0x80000000为例,右移一位的时候, 并不是简单地把最高位的1移到第二位变成0x40000000, 而是0xC0000000。 这是因为移位前是个负数,仍然要保证移位后是个负数, 因此移位后的最高位会设为1。 如果一直做右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环。 为了避免死循环,我们可以不右移输入的数字i。 首先i和1做与运算,判断i的最低位是不是为1。 接着把1左移一位得到2,再和i做与运算,就能判断i的次高位是不是1…… 这样反复左移,每次都能判断i的其中一位是不是1。 基于此,我们得到如下代码: /////////////////////////////////////////////////////////////////////// //Gethowmany1sinaninteger'sbinaryexpression /////////////////////////////////////////////////////////////////////// intNumberOf1_Solution2(inti) { intcount=0; unsignedintflag=1; while(flag) { if(i&flag) count++; flag=flag<<1; } returncount; } 29.栈的push、pop序列 题目: 输入两个整数序列。 其中一个序列表示栈的push顺序, 判断另一个序列有没有可能是对应的pop顺序。 如果我们希望pop的数字正好是栈顶数字,直接pop出栈即可; 如果希望pop的数字目前不在栈顶,我们就到 push序列中还没有被push到栈里的数字中去搜索这个数字, 并把在它之前的所有数字都push进栈。 如果所有的数字都被push进栈仍然没有找到这个数字,表明该序列不可能是一个pop序列。 //////////////////////////////////// 我们来着重分析下此题: push序列已经固定, pushpop ------>/----> 54321/45321 |5| |4| |3| |2| |___1__| 1.要得到45321的pop序列,即pop的顺序为4->5->3->2->1 首先,要pop4,可让push5之前,pop4,然后push5,pop5 然后发现3在栈顶,直接pop3..2..1 2.再看一序列, pushpop ------>/----> 54321/43512 |5| |4| |3| |2| |___1__| 想得到43512的pop序列,是否可能? 4->3->5->1->2 同样在push5之前,push了4321,pop4,pop3,然后再push5,pop5 2 再看栈中的从底至上是1,由于12已经在栈中,所以只能先pop2,才能pop1。 所以,很显然,不可能有43512的pop序列。 所以上述那段注释的话的意思,即是, 如果,一个元素在栈顶,直接pop即可。 如果它不在栈顶,那么从push序列中找这个元素 找到,那么push它,然后再pop它。 否则,无法在那个顺序中pop。 ////////////////////////////////////// push序列已经固定, pushpop ------>/----> 54321/35421//可行 |5|14532//亦可行,不知各位,是否已明了题意? : ).. |4| |3| |2| |___1__| /////////////////////////////////////////////// 今早我也来了,呵。 昨晚,后来,自个又想了想,要怎么才能pop想要的一个数列? push序列已经固定, pushpop ------>/----> 54321/54321 |5| |4| |3| |2| |___1__| 比如,当栈中已有数列2 1 而现在我随机要pop4,一看,4不在栈中,再从push序列中, 正好,4在push队列中,push4进栈之前,还得把4前面的数,即3先push进来,。 好,现在,push3,push4,然后便是想要的结果: pop4。 所以,当我要pop一个数时,先看这个数在不在已经push的栈顶,如果,在,好,直接pop它。 如果,不在,那么,从push序列中,去找这个数,找到后,push它进栈, 如果push队列中它的前面还有数,那么还得把它前面数,先push进栈。 如果铺设队列中没有这个数,那当然就不是存在这个pop结果了。 不知,我说明白了没? : ).接下来,给一段,参考程序: //有误之处,恳请指正。 July、2010/11/09。 : )。 boolIsPossiblePopOrder(constint*pPush,constint*pPop,intnLength) { boolbPossible=false; if(pPush&&pPop&&nLength>0) { constint*pNextPush=pPush; constint*pNextPop=pPop; //ancillarystack std: : stack //checkeveryintegersinpPop while(pNextPop-pPop { //whilethetopoftheancillarystackisnottheinteger //tobepoped,trytopushsomeintegersintothestack while(stackData.empty()||stackData.top()! =*pNextPop) { //pNextPush==NULLmeansallintegershavebeen //pushedintothestack,can'tpushanylonger if(! pNextPush) break; stackData.push(*pNextPush); //ifthereareintegersleftinpPush,move //pNextPushforward,otherwisesetittobeNULL if(pNextPush-pPush pNextPush++; else pNextPush=NULL; } //
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中间 试题 答案