网易面试题目
1). 如果n>m,则n中大于m的应该忽略,置n=m
2). 将最大数n加入组合,如果n==m,直接输出
3). 两种情况,n加入,在1到n-1中求子问题=m-n,n不加入,在1到n-1求子问题=m
void findEqual(unsigned n,int sum,int *flag) { if(n<0 || m <0) return -1 if(n>m) n=m if(n==m) { flag[n-1]=1 printFlag(flag) flag[n-1]=0 } flag[n-1]=0 findEqual(n-1,m,flag) flag[n-1]=1 findEqual(n-1,m-n,flag) }
3. 一串首尾相连的珠子(m个), 有N种颜色(N<=10),设计算法,取出其中一段,要求包含所有N中颜色,并使长度最短。分析时间与空间复杂度。
类似题目:给定一个很长的字符串str还有一个字符集比如{a,b,c}找出str里包含{a,b,c}的最短子串
比如,字符集是a,b,c,字符串是abdcaabc,则最短子串为abc
区别:前者带坏,后者不带环
解法:两个指针pHead,pNext,用数组color记录当前已有颜色及其个数
1). pNext++,直接color所有的颜色都出现,记录为最佳序列
2). pHead++,相应的color的--,如果某个颜色的count=1,则和之前记录的最佳序列比较,更新最佳序列
3). pHead++
4). PNext++直接所有颜色都出现,重复2,3,4步骤
其中,pNext=pNext%m
结束条件:无环:pNext = m ,有环:pHead = m
4. 我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。
根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。我们假设数组中已经有若干个丑数,排好序后存在数组中。我们把现有的最大丑数记做M。现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以2、3或者5的结果。我们首先考虑把已有的每个丑数乘以2。我们把得到的第一个乘以2后大于M的结果,记为M2,同样有M3和M5。那么下一个丑数应该是M2、M3和M5三个数的最小者。
前面我们分析的时候,提到把已有的每个丑数分别都乘以2、3和5,事实上是不需要的,因为已有的丑数是按顺序存在数组中的。对乘以2而言,肯定存在某一个丑数T2,排在它之前的每一个丑数乘以2得到的结果都会小于已有最大的丑数,在它之后的每一个丑数乘以2得到的结果都会太大。我们只需要记下这个丑数的位置,同时每次生成新的丑数的时候,去更新这个T2。对乘以3和5而言,存在着同样的T3和T5。
int GetUglyNumber_Solution2(int index) { if(index <= 0) return 0; int *pUglyNumbers = new int[index]; pUglyNumbers[0] = 1; int nextUglyIndex = 1; int *pMultiply2 = pUglyNumbers; int *pMultiply3 = pUglyNumbers; int *pMultiply5 = pUglyNumbers; while(nextUglyIndex < index) { int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5); pUglyNumbers[nextUglyIndex] = min; while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex]) ++pMultiply2; while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex]) ++pMultiply3; while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex]) ++pMultiply5; ++nextUglyIndex; } int ugly = pUglyNumbers[nextUglyIndex - 1]; delete[] pUglyNumbers; return ugly; } int Min(int number1, int number2, int number3) { int min = (number1 < number2) ? number1 : number2; min = (min < number3) ? min : number3; return min; }
4. 有A、B、C、D四个人,要在夜里过一座桥。通过这座桥分别需要耗时1、2、5、10分钟,只有一支手电,并且同时最多只能两个人一起过桥。请问,如何安排,能够在17分钟内这四个人都过桥?
第一趟过去:两人:花1分钟和2分钟的人 //总共耗时:2分钟
第一趟过来:一人:花1分钟的人 //总共耗时:3分钟
第二趟过去:两人:花5分钟和10分钟的人 //总共耗时:13分钟
第二趟过来:一人:花2分钟的人 //总共耗时:15分钟
第三趟过去:两人:花1分钟和2分钟的人 //总共耗时:17分钟
5. 地面上有无数的随机硬币,现在有一个人负责每天对这些硬币进行操作,操作如下:如果硬币是反面的,就把它翻过来;如果是正面的就随机抛一下;如此以往,到n天以后正面和反面的比例是否能够达到一个稳定的比例,如果能,求比例是多少。
假设硬币正面朝上为pos,反面朝上为neg,假设第n天处于pos状态的硬币数为an , neg状态的硬币数为bn,则最终所求的是an/bn 。
由已知条件得:
an+1 = an/2 + bn
bn+1 = an/2
所以带入后,两边同除以an得到: 2an+1/an = 1+an-1/an
由于是一个求极限问题,所以可以转化为:2x = 1+1/x
又x不小于零,所以解得x = 1,所以: an/bn = 2an+1/an =2
n天后将会达到极限值2
6. 如果一个整数能够表示成两个或多个素数之和,则得到一个素数和分解式。对于一个给定的整数,输出所有这种素数和分解式。注意,对于同构的分解只输出一次(比如5只有一个分解2 + 3,而3 + 2是2 + 3的同构分解式)。
例如,对于整数8,可以作为如下三种分解:
(1) 8 = 2 + 2 + 2 + 2
(2) 8 = 2 + 3 + 3
(3) 8 = 3 + 5
关键问题:得到小与n的所有素数表
void GetPrimes(int n,vector<int>& Prime) { Prime.push_back(2); for(int i=3;i<=n;++i) { int k; for(k=2;k*k<=i;++k) if(i%k==0) break; if(k*k>i) Prime.push_back(i); } } void Func(int n,int begin,vector<int>& Prime) { static vector<int> V; if(n<0) return; else if(n==0) { for(vector<int>::iterator it=V.begin();it!=V.end();++it) cout <<*it<<" "; cout <<endl; } else { int num=Prime.size(); //保证不同构 for(int i=begin;i<num;++i) { V.push_back(Prime[i]); Func(n-Prime[i],i,Prime); V.pop_back(); } } }