曾记否,去年的10月份也同此刻一样,是找工作的高峰期,本博客便是最初由整理微软等公司面试题而发展而来的。如今,又即将迈入求职高峰期--10月份,而本人也正在找下一份工作中 ,所以,也不免关注了网上和我个人建的算法群Algorithms1-12群(第1-11群已满,Algorithms_12群,53403981 )内朋友发布和讨论的最新面试题。特此整理,以飨诸位。至于答案,望诸位共同讨论与思考。
自从公布Algorithms_9群-11群的群号以来,一般一个星期之内满员。不免被各位的热情所震撼(包括本文评论下奉献自己的思路的朋友,非常感谢)。希望,各位既然加进来,便多多参与讨论下文中的面试题,一起学习、思考,以期共同进步。谢谢。
最新面试十三题
好久没有好好享受思考了。ok,任何人有任何意见或问题,欢迎不吝指导:
- 五只猴子分桃。半夜,第一只猴子先起来,它把桃分成了相等的五堆,多出一只。于是,它吃掉了一个,拿走了一堆; 第二只猴子起来一看,只有四堆桃。于是把四堆合在一起,分成相等的五堆,又多出一个。于是,它也吃掉了一个,拿走了一堆;.....其他几只猴子也都是 这样分的。问:这堆桃至少有多少个?(朋友说,这是小学奥数题)。
参考答案:先给这堆桃子加上4个,设此时共有X个桃子,最后剩下a个桃子.这样:
第一只猴子分完后还剩:(1-1/5)X=(4/5)X;
第二只猴子分完后还剩:(1-1/5)2X;
第三只猴子分完后还剩:(1-1/5)3X;
第四只猴子分完后还剩:(1-1/5)4X;
第五只猴子分完后还剩:(1-1/5)5X=(1024/3125)X;
得:a=(1024/3125)X;
要使a为整数,X最小取3125.
减去加上的4个,所以,这堆桃子最少有3121个。 - 已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10 。
(参考答案:这题主要考的是对概率的理解。程序关键是要算出rand10,1到10,十个数字出现的考虑都为10%.根据排列组合,连续算两次rand7出现的组合数是7*7=49,这49种组合每一种出现考虑是相同的。怎么从49平均概率的转换为1到10呢?方法是:
1.rand7执行两次,出来的数为a1.a2.
2.如果a1*7+a2<40,b=(a1*7+a2)/4+1,如果a1*7*a2>=40,重复第一步)。参考代码如下所示:- int rand7()
- {
- return rand()%7+1;
- }
- int rand10()
- {
- int a71,a72,a10;
- do
- {
- a71= rand7()-1;
- a72 = rand7()-1;
- a10 = a71 *7 + a72;
- } while (a10>= 40);
- return (a71*7+a72)/4+1;
- }
- 如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。
- 要求设计一个DNS的Cache结构,要求能够满足每秒5000以上的查询,满足IP数据的快速插入,查询的速度要快。
- 一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的 相对顺序 比如: input: 1,7,-5,9,-12,15 ans: -5,-12,1,7,9,15 要求时间复杂度O(N),空间O(1) 。(此题一直没看到令我满意的答案,一般达不到题目所要求的:时间复杂度O(N),空间O(1) )
- 淘宝面试题:有一个一亿节点的树,现在已知两个点,找这两个点的共同的祖先。
- 海量数据分布在100台电脑中,想个办法高效统计出这批数据的TOP10。(此题请参考本博客内其它文章)。
-
某服务器流量统计器,每天有1000亿的访问记录数据,包括时间、url、ip。设计系统实现记录数据的
保存、管理、查询。要求能实现一下功能:
(1)计算在某一时间段(精确到分)时间内的,某url的所有访问量。
(2)计算在某一时间段(精确到分)时间内的,某ip的所有访问量。 -
假设某个网站每天有超过10亿次的页面访问量,出于安全考虑,网站会记录访问客户端访问的ip地址和对应的时间,如果现在已经记录了1000亿条数据,想统计一个指定时间段内的区域ip地址访问量,那么这些数据应该按照何种方式来组织,才能尽快满足上面的统计需求呢,
设计完方案后,并指出该方案的优缺点,比如在什么情况下,可能会非常慢?(参考答案:用B+树来组织,非叶子节点存储(某个时间点,页面访问量),叶子节点是访问的IP地址。这个方案的优点是查询某个时间段内的IP访问量很快,但是要统计某个IP的访问次数或是上次访问时间就不得不遍历整个树的叶子节点。 或者可以建立二级索引,分别是时间和地点来建立索引。 ) -
腾讯1.服务器内存1G,有一个2G的文件,里面每行存着一个QQ号(5-10位数),怎么最快找出出现过最多次的QQ号。
腾讯2.如何求根号2的值,并且按照我的需要列出指定小数位,比如根号2是1.141 我要列出1位小数就是1.1 2位就是1.14, 1000位就是1.141...... 等。。 -
-
- 我们有很多瓶无色的液体,其中有一瓶是毒药,其它都是蒸馏水,实验的小白鼠喝了以后会在5分钟后死亡,而喝到蒸馏水的小白鼠则一切正常。现在有5只小白鼠,请问一下,我们用这五只小白鼠,5分钟的时间,能够检测多少瓶液体的成分?
淘宝2012笔试(研发类):http://topic.csdn.net/u/20110922/10/e4f3641a-1f31-4d35-80da-7268605d2d51.html (一参考答案 )。
ok,这13道题加上此前本博客陆陆续续整理的微软面试187题:重启开源,分享无限--诚邀你加入微软面试 18 7 题 的解题中 ,至此,本博客内已经整理了整整200道 面试题。
同时,也算是由于本博客在开博不到一年的时间内 (2010.10.14-2011.09.19 )突破100万流量 而对读者的支持和青睐表示感谢。有任何问题或思路,欢迎不吝赐教(或者来信指导:[email protected] )。谢谢。July、二零一一年九月二十三日。
后续整理
以下是后续整理的最新面试题,不断更新中(2011.09.26).....
14 、腾讯最新面试题:服务器内存1G,有一个2G的文件,里面每行存着一个QQ号(5-10位数),怎么最快找出出现过最多次的QQ号。
15 、百度今天的笔试题:在一维坐标轴上有n个区间段,求重合区间最长的两个区间段。
16 、华为社招现场面试1:请使用代码计算1234567891011121314151617181920*2019181716151413121110987654321 。
华为面试2:1分2分5分的硬币,组成1角,共有多少种组合。
17 、百度笔试题:
一、系统有很多任务,任务之间有依赖,比如B依赖于A,则A执行完后B才能执行
(1)不考虑系统并行性,设计一个函数(Task *Ptask,int Task_num)不考虑并行度,最快的方法完成所有任务。
(2)考虑并行度,怎么设计
typedef struct{
int ID;
int * child;
int child_num;
}Task;
提供的函数:
bool doTask(int taskID);无阻塞的运行一个任务;
int waitTask(int timeout);返回运行完成的任务id,如果没有则返回-1;
bool killTask(int taskID);杀死进程二、必答题(各种const)
1、解释下面ptr含义和不同
double* ptr = &value;
//ptr是一个指向double类型的指针,ptr的值可以改变,ptr所指向的value的值也可以改变
const double* ptr = &value
//ptr是一个指向const double类型的指针,ptr的值可以改变,ptr所指向的value的值不可以改变
double* const ptr=&value
//ptr是一个指向double类型的指针,ptr的值不可以改变,ptr所指向的value的值可以改变
const double* const ptr=&value
//ptr是一个指向const double类型的指针,ptr的值不可以改变,ptr所指向的value的值也不可以改变
2、去掉const属性,例: const double value = 0.0f; double* ptr = NULL;怎么才能让ptr指向value?
强制类型转换,去掉const属性,如ptr =(&value); http://topic.csdn.net/u/20110925/16/e6248e53-1145-4815-8d24-9c9019d24bd8.html?seed=1665205011&r=75709169#r_75709169
18 、如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头指针front,不设队列尾指针rear,求这个队列中从队列投到队列尾的元素个数(包含队列头、队列尾)(华赛面试题、腾讯笔试题)。
19 、昨晚淘宝笔试题:
1. 设计相应的数据结构和算法,尽量高效的统计一片英文文章(总单词数目)里出现的所有英文单词,按照在文章中首次出现的顺序打印输出该单词和它的出现次数。
2、有一棵树(树上结点为字符串或者整数),请写代码将树的结构和数据写到一个文件中,并能通过读取该文件恢复树结构 。
20 、13个球一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个球?(http://zhidao.baidu.com/question/66024735.html
)。21 、搜狗笔试题:一个长度为n的数组a[0],a[1],...,a[n-1]。现在更新数组的名个元素,即a[0]变为a[1]到a[n-1]的积,a[1]变为a[0]和a[2]到a[n-1]的积,...,a[n-1]为a[0]到a[n-2]的积。
程序要求:
要求具有线性复杂度。
不能使用除法运算符。
参考答案@MESH4444:
3步搞定(假设乘法是一次运算)……
1、累乘:计算a1*a2, a1*a2*a3, ......, a1*a2*...*an——复杂度n-1
2、累乘:计算an*a(n-1), an*a(n-1)*a(n-2), ......, an*a(n-1)*a(n-2)*...*a1——复杂度n-1
3、求积:找到对应数值,直接再做一次乘法得结果——复杂度为n这样,复杂度就是3n-2,也就是O(3n)
22 、腾讯高水平复试题:
1.有不同的手机终端,如iphone,安卓,Symbian,不同的终端处理不一样,设计一种服务器和算法实现对不同的终端的处理。
2.设计一种内存管理算法。
3.A向B发邮件,B收到后读取并发送收到,但是中间可能丢失了该邮件,怎么设计一种最节省的方法,来处理丢失问题。
4.设计一种算法求出算法复杂度 。23 、人人笔试1:一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法?人人笔试2:在人人好友里,A和B是好友,B和C是好友,如果A 和C不是好友,那么C是A的二度好友,在一个有10万人的数据库里,如何在时间0(n)里,找到某个人的十度好友。24 、淘宝算法面试题:两个用户之间可能互相认识,也可能是单向的认识,用什么数据结构来表示?如果一个用户不认识别人,而且别人也不认识他,那么他就是无效节点,如何找出这些无效节点?自定义数据接口并实现之,要求尽可能节约内存和空间复杂度。
更新至2011.09.29....
异常感谢本文评论中各位奉献的自己的思路( 贴代码的时候,勿忘简单描述下思路) ,望各位继续思考和讨论,偶亦可多多学习与参考。同时,不断整理出新的面试题。July、2011.09.26。
- int i = 0, count, tmp;
- while (1)
- {
- tmp = ++i;
- for (count = 0; count < 5; count++)
- {
- tmp = ((tmp-1) % 5 == 0)?(tmp-1)/5*4:-1;
- if (tmp <= 0)
- break ;
- }
- if (count == 5)
- break ;
- }
- printf( "The result is %d\n" , i);
int i = 0, count, tmp; while(1) { tmp = ++i; for(count = 0; count < 5; count++) { tmp = ((tmp-1) % 5 == 0)?(tmp-1)/5*4:-1; if(tmp <= 0) break; } if(count == 5) break; } printf("The result is %d\n", i);
- #include
- void nswapvalue( int *arr, int i , int j) { // change positive to negative
- int m = arr[i];
- arr[i] = arr[j];
- arr[j] = -m;
- }
- void pswapvalue( int *arr, int i , int j) { //change negative to positive
- int m = arr[i];
- arr[i] = -arr[j];
- arr[j] = m;
- }
- int swaploop( int *arr, int size){ //思想:执行一次循环,把所有负数置换到前面,可以保证负数的相对位置不变
- int cur = 0,count=0,i;
- for (i = 0 ;i < size; ++i){ // 把所有负数提前,并把置换到后面的整数变为负数
- if (arr[i]>0 && cur ==0){
- cur = i; //cur 始终指向最前面的整数
- }
- if (arr[i]<0 && cur < i){
- nswapvalue(arr,cur,i);
- ++cur;
- ++count; //记录负数的个数
- }
- }
- for (i = count ;i < size; ++i){ //处理原始负数以后的数据,并把上面变为负数的正数变回来
- if (arr[i]>0 && cur ==0){
- cur = i;
- }
- if (arr[i]<0 && cur < i){
- pswapvalue(arr,cur,i);
- ++cur;
- }
- }
- }
#includevoid nswapvalue(int *arr,int i , int j) { // change positive to negative int m = arr[i]; arr[i] = arr[j]; arr[j] = -m; } void pswapvalue(int *arr,int i , int j) {//change negative to positive int m = arr[i]; arr[i] = -arr[j]; arr[j] = m; } int swaploop(int *arr,int size){//思想:执行一次循环,把所有负数置换到前面,可以保证负数的相对位置不变 int cur = 0,count=0,i; for(i = 0 ;i < size; ++i){ // 把所有负数提前,并把置换到后面的整数变为负数 if(arr[i]>0 && cur ==0){ cur = i; //cur 始终指向最前面的整数 } if(arr[i]<0 && cur < i){ nswapvalue(arr,cur,i); ++cur; ++count; //记录负数的个数 } } for(i = count ;i < size; ++i){ //处理原始负数以后的数据,并把上面变为负数的正数变回来 if(arr[i]>0 && cur ==0){ cur = i; } if(arr[i]<0 && cur < i){ pswapvalue(arr,cur,i); ++cur; } } }
输入int arr[10] = { -1,2,3,4,-5,6,-7,8,-9,10 };
int size = 10;
出来的结果是:-1,-5,-7,-9,3,4,-2,8,6,10;
请验证!
int fun(int n)
{
int f;
if(n <= 3)
{
f = pow(double(2),(n-1));
}
else
{
f = fun(n - 1) + fun(n - 2) + fun(n - 3);
}
return f;
}
int main(void)
{
int n = 7;//台阶总数
int sum;
sum = fun(n);
printf("%d\n",sum);
}
1.迭代
- int GetMaxStepNormal( int n)
- {
- if (n<=0) return 0;
- if (n==1) return 1;
- if (n==2) return 2;
- if (n==3) return 4;
- int r,r1=1,r2=2,r3=4;
- for ( int i=3;i
- {
- r=r1+r2+r3;
- r1=r2;
- r2=r3;
- r3=r;
- }
- return r;
- }
int GetMaxStepNormal(int n) { if(n<=0) return 0; if(n==1) return 1; if(n==2) return 2; if(n==3) return 4; int r,r1=1,r2=2,r3=4; for(int i=3;i
2.递归,注意保存以计算的结果
int GetMaxStepMain( int , int *);
int GetMaxStepRecurs( int n)
{
int * calc;
int r;
if (n<=0) return 0;
calc= new int [n];
if (NULL==calc) return 0;
for ( int i=0;i=0; delete calc;
r= GetMaxStepMain(n,calc);
return r;
}
int GetMaxStepMain( int n, int * a)
{
int t[3];
if (n==1) return 1;
if (n==2) return 2;
if (n==3) return 4;
for ( int i=3;i>0;i--)
{
if (a[n-i]==0)
{
t[i-1]=GetMaxStepMain(n-i,a);
a[n-i]=t[i-1];
}
else
{
t[i-1]=a[n-i];
}
}
return t[0]+t[1]+t[2];
}
int GetMaxStepMain(int ,int*); int GetMaxStepRecurs(int n) { int* calc; int r; if(n<=0) return 0; calc=new int[n]; if(NULL==calc) return 0; for(int i=0;i=0; r= GetMaxStepMain(n,calc); delete calc; return r; } int GetMaxStepMain(int n,int* a) { int t[3]; if(n==1) return 1; if(n==2) return 2; if(n==3) return 4; for(int i=3;i>0;i--) { if(a[n-i]==0) { t[i-1]=GetMaxStepMain(n-i,a); a[n-i]=t[i-1]; } else { t[i-1]=a[n-i]; } } return t[0]+t[1]+t[2]; }
- #include
- #include
- int brothstr( const char *s1, int len1, const char *s2, int len2){
- if (len1 != len2) return 0;
- int box[128] = {0};
- int i;
- //pack into box
- for (i=0;i
- int v = s1[i];
- ++box[v];
- }
- //remove from box
- for (i=0;i
- int v = s2[i];
- --box[v];
- }
- // is the box empty?
- for (i=0;i
- int v = s1[i];
- if (box[v]>0) return 0;
- }
- return 1;
- }
- int main( int argc, const char *argv[])
- {
- if (argc!=3){
- printf( "%s s1 s2\n" ,argv[0]);
- return 1;
- }
- char *s1 = ( char *)argv[1];
- int l1 = strlen(s1);
- char *s2 = ( char *)argv[2];
- int l2 = strlen(s2);
- int isborther = brothstr(s1,l1,s2,l2);
- isborther? printf( "is brother\n" ,s1,s2):printf( "is not brother\n" ,s1,s2);
- return 0;
- }
#include#include int brothstr(const char *s1,int len1,const char *s2,int len2){ if(len1 != len2)return 0; int box[128] = {0}; int i; //pack into box for(i=0;i 0)return 0; } return 1; } int main(int argc, const char *argv[]) { if(argc!=3){ printf("%s s1 s2\n",argv[0]); return 1; } char *s1 = (char*)argv[1]; int l1 = strlen(s1); char *s2 = (char*)argv[2]; int l2 = strlen(s2); int isborther = brothstr(s1,l1,s2,l2); isborther? printf("is brother\n",s1,s2):printf("is not brother\n",s1,s2); return 0; }
对于i, j, k的确定,我们可以用从大到小划分法, 先划分3的次数,再划分2的次数,剩下的都算做1的次数,具体程序中就是里面的i,j,两重循环.
- //23、人人笔试1:一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法?
- //思路,建模分析得出结果是 所有 (i+j+k)!/(i!*j!*k!) 的和,其中i,j,k满足条件 3*i+2*j+k=n
- //以下解法暂不考虑数据过大的溢出问题
- int CItems::NStepFor123( int n)
- {
- int i=0;
- int j=0;
- int p;
- int k;
- int result=0;
- for ( i=0; i<=n/3; i++ )
- {
- p = n-i*3;
- for ( j=0; j<=p/2; j++ )
- {
- k = p -j*2;
- //求(i+j+k)!/(i!*j!*k!)
- result += GetComb(i,j,k);
- }
- }
- return result;
- }
//23、人人笔试1:一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法? //思路,建模分析得出结果是 所有 (i+j+k)!/(i!*j!*k!) 的和,其中i,j,k满足条件 3*i+2*j+k=n //以下解法暂不考虑数据过大的溢出问题 int CItems::NStepFor123(int n) { int i=0; int j=0; int p; int k; int result=0; for ( i=0; i<=n/3; i++ ) { p = n-i*3; for ( j=0; j<=p/2; j++ ) { k = p -j*2; //求(i+j+k)!/(i!*j!*k!) result += GetComb(i,j,k); } } return result; }
- int CItems::GetComb( int i, int j, int k)
- {
- if ( i+j+k<0 || i<0 || j<0 || k<0)
- {
- return 0;
- }
- int den=1; //分母
- int mun=1; //分子
- int p; //临时变量
- for ( p = 1;p<=i+j+k; p++ ) //求分子
- {
- mun*=p;
- }
- if (i>0) //求分母中i!部分
- {
- for ( p = 1;p<=i; p++ )
- {
- den*=p;
- }
- }
- if (j>0) //求分母中i!j!部分
- {
- for ( p = 1;p<=j; p++ )
- {
- den*=p;
- }
- }
- if (k>0) //求分母总值
- {
- for ( p = 1;p<=k; p++ )
- {
- den*=p;
- }
- }
- return ( int )(mun/den); //可以用数学方法证明此除法得出的一定是整数
- }
int CItems::GetComb(int i,int j,int k) { if ( i+j+k<0 || i<0 || j<0 || k<0) { return 0; } int den=1;//分母 int mun=1;//分子 int p; //临时变量 for ( p = 1;p<=i+j+k; p++ )//求分子 { mun*=p; } if (i>0) //求分母中i!部分 { for ( p = 1;p<=i; p++ ) { den*=p; } } if (j>0)//求分母中i!j!部分 { for ( p = 1;p<=j; p++ ) { den*=p; } } if (k>0)//求分母总值 { for ( p = 1;p<=k; p++ ) { den*=p; } } return (int)(mun/den);//可以用数学方法证明此除法得出的一定是整数 }
int StepRes1;
for ( int i =1; i<20; i++ )
{
StepRes1 = item.NStepFor123(i);
printf("\n%d step for 1,2,3 method is %d",i,StepRes1);
}
结果如下:
1 step for 1,2,3 method is 1
2 step for 1,2,3 method is 2
3 step for 1,2,3 method is 4
4 step for 1,2,3 method is 7
5 step for 1,2,3 method is 13
6 step for 1,2,3 method is 24
7 step for 1,2,3 method is 44
8 step for 1,2,3 method is 81
9 step for 1,2,3 method is 149
10 step for 1,2,3 method is 274
11 step for 1,2,3 method is 504
12 step for 1,2,3 method is 927
13 step for 1,2,3 method is1705
14 step for 1,2,3 method is 3127
15 step for 1,2,3 method is 5691
16 step for 1,2,3 method is 10185
17 step for 1,2,3 method is 17695
18 step for 1,2,3 method is 29465
19 step for 1,2,3 method is 46435
- document.write( "没一个会的!" )
document.write("没一个会的!")
- //搜狗笔试题:一个长度为n的数组a[0],a[1],...,a[n-1]。现在更新数组的名个元素,即a[0]变为a[1]到a[n-1]的积,a[1]变为a[0]和a[2]到a[n-1]的积,...,a[n-1]为a[0]到a[n-2]的积。
- //程序要求:
- //要求具有线性复杂度。
- //不能使用除法运算符。
- #define MAX_ARRAY_SIZE 9
- void CItems::GetMultiplay()
- {
- int Array[MAX_ARRAY_SIZE]={1,2,3,4,5,6,7,8,9};
- int temp1[MAX_ARRAY_SIZE]={0};
- int temp2[MAX_ARRAY_SIZE]={0};
- temp1[0] = Array[0];
- temp2[MAX_ARRAY_SIZE-1] = Array[MAX_ARRAY_SIZE-1];
- for ( int j=1; j
- {
- temp1[j] = temp1[j-1]*Array[j];
- temp2[MAX_ARRAY_SIZE-1-j] = temp2[MAX_ARRAY_SIZE-j]*Array[MAX_ARRAY_SIZE-1-j];
- }
- Array[0] = temp2[1];
- Array[MAX_ARRAY_SIZE-1] = temp1[MAX_ARRAY_SIZE-2];
- for ( int i = 1; i
- {
- Array[i]=temp1[i-1]*temp2[i+1];
- }
- for ( int k = 0; k
- {
- printf( "Array[%d]=%d" ,i,Array[i]);
- }
- return ;
- }
//搜狗笔试题:一个长度为n的数组a[0],a[1],...,a[n-1]。现在更新数组的名个元素,即a[0]变为a[1]到a[n-1]的积,a[1]变为a[0]和a[2]到a[n-1]的积,...,a[n-1]为a[0]到a[n-2]的积。 //程序要求: //要求具有线性复杂度。 //不能使用除法运算符。 #define MAX_ARRAY_SIZE 9 void CItems::GetMultiplay() { int Array[MAX_ARRAY_SIZE]={1,2,3,4,5,6,7,8,9}; int temp1[MAX_ARRAY_SIZE]={0}; int temp2[MAX_ARRAY_SIZE]={0}; temp1[0] = Array[0]; temp2[MAX_ARRAY_SIZE-1] = Array[MAX_ARRAY_SIZE-1]; for ( int j=1; j
- int cacl( int mouse_count, int bottle_count)
- {
- int res = 0;
- for ( i = 1; i <= mouse_count; i++ ) {
- res += bottle_count/(1<
- }
- return res;
- }
int cacl(int mouse_count, int bottle_count) { int res = 0; for ( i = 1; i <= mouse_count; i++ ) { res += bottle_count/(1<
第二题,不知此解如何?
- int rand10()
- {
- int a, b;
- do {
- a = rand7();
- } while ( a > 5 );
- do {
- b = rand7();
- } while ( b > 2 );
- return a*2-(b-1);
- }
int rand10() { int a, b; do { a = rand7(); } while ( a > 5 ); do { b = rand7(); } while ( b > 2 ); return a*2-(b-1); }
最近太多了,暂时不看了。
mark一下。
private int getRand10()
{
int a=rand(7);
int b=rand(7);
if((a+b)<11)
return a+b;
}
- char const * MI(string const &...[/quote]
- 接着
- [code=cpp]
- char const * Add(string& x, string const & y)
- {
- char const * px = x.c_str();
- char const * py = y.c_str();
- char const * pxe = px + x.length();
- char const * pye = py + y.length();
- int carry = 0;
- list< char > r;
- for (--pxe, --pye; pxe >= px && pye >= py; --pxe, --pye)
- {
- int i = (*pxe - '0' ) + (*pye - '0' ) + carry;
- carry = i / 10;
- i %= 10;
- r.push_front(i + '0' );
- }
- for (; pxe >= px; --pxe)
- {
- int i = (*pxe - '0' ) + carry;
- carry = i / 10;
- i %= 10;
- r.push_front(i + '0' );
- }
- for (; pye >= py; --pye)
- {
- int i = (*pye - '0' ) + carry;
- carry = i / 10;
- i %= 10;
- r.push_front(i + '0' );
- }
- return x.assign(r.begin(), r.end() ).c_str();
- }
char const* MI(string const&...[/quote] 接着 [code=cpp] char const* Add(string& x, string const& y) { char const* px = x.c_str(); char const* py = y.c_str(); char const* pxe = px + x.length(); char const* pye = py + y.length(); int carry = 0; listr; for (--pxe, --pye; pxe >= px && pye >= py; --pxe, --pye) { int i = (*pxe - '0') + (*pye - '0') + carry; carry = i / 10; i %= 10; r.push_front(i + '0'); } for (; pxe >= px; --pxe) { int i = (*pxe - '0') + carry; carry = i / 10; i %= 10; r.push_front(i + '0'); } for (; pye >= py; --pye) { int i = (*pye - '0') + carry; carry = i / 10; i %= 10; r.push_front(i + '0'); } return x.assign(r.begin(), r.end() ).c_str(); }
- char const * MI(string const & x, int y, int z, string &s)
- {
- list< char > r;
- int carry = 0;
- for ( char const * p = x.c_str(), *pe = x.c_str() + x.length() - 1; pe >= p; --pe)
- {
- int i = (*pe - '0' ) * y + carry;
- carry = i / 10;
- i %= 10;
- r.push_front(i + '0' );
- }
- if (carry > 0)
- {
- r.push_front(carry + '0' );
- }
- for (; z > 0; --z)
- {
- r.push_back( '0' );
- }
- return s.assign(r.begin(), r.end() ).c_str();
- }
char const* MI(string const& x, int y, int z, string &s) { listr; int carry = 0; for (char const* p = x.c_str(), *pe = x.c_str() + x.length() - 1; pe >= p; --pe) { int i = (*pe - '0') * y + carry; carry = i / 10; i %= 10; r.push_front(i + '0'); } if (carry > 0) { r.push_front(carry + '0'); } for (; z > 0; --z) { r.push_back('0'); } return s.assign(r.begin(), r.end() ).c_str(); }
我用的都是java自带的排序
import java.util.Arrays;
public class Test{
public static void main(String[] args)
{
String str1="abc";
String str2="bca";
char[] arr1=str1.toCharArray();
char[] arr2=str2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
str1=new String(arr1);
str2=new String(arr2);
if(str1.equals(str2)){
System.out.println("是兄弟串");
}else{
System.out.println("不是兄弟串");
}
}
}
- void PartitionSort( int q[], int n)
- {
- for ( int i=n-1, k=0; i>=0; i--)
- {
- if (q[i] >= 0)
- {
- if (k == 0) continue ;
- int t = q[i];
- memmove(&q[i], &q[i+1], k* sizeof ( int ));
- q[i+k] = t;
- }
- else
- k++;
- }
- }
void PartitionSort(int q[], int n) { for (int i=n-1, k=0; i>=0; i--) { if (q[i] >= 0) { if (k == 0) continue; int t = q[i]; memmove(&q[i], &q[i+1], k*sizeof(int)); q[i+k] = t; } else k++; } }
- int total = 0;
- for ( int i = 0; i < 10; i++)
- {
- total += Rand7();
- }
- return total / 7;
int total = 0; for (int i = 0; i < 10; i++) { total += Rand7(); } return total / 7;
这个方法有点强盗逻辑,OTZ不过确实很巧妙……
- int rand7();
- int Random10()
- {
- int k, i;
- while (1)
- {
- int i = rand7();
- if (i < 6)
- {
- k = i;
- break ;
- }
- }
- while (1)
- {
- int i = rand7();
- if (i < 7)
- {
- if (i < 4)
- {
- k = k + 5;
- }
- break ;
- }
- }
- return k;
- }
int rand7(); int Random10() { int k, i; while(1) { int i = rand7(); if(i < 6) { k = i; break; } } while(1) { int i = rand7(); if(i < 7) { if(i < 4) { k = k + 5; } break; } } return k; }
- int X( int iMonkey, int & iPerMonkey)
- {
- if (1 == iMonkey)
- {
- return 5 * iPerMonkey + 1;
- }
- int iLeft = X(iMonkey - 1, iPerMonkey);
- while (iLeft % 4)
- {
- iLeft = X(iMonkey - 1, ++iPerMonkey);
- }
- return 1 + 5 * iLeft / 4;
- }
int X(int iMonkey, int& iPerMonkey) { if (1 == iMonkey) { return 5 * iPerMonkey + 1; } int iLeft = X(iMonkey - 1, iPerMonkey); while (iLeft % 4) { iLeft = X(iMonkey - 1, ++iPerMonkey); } return 1 + 5 * iLeft / 4; }
import java.util.Set;
import java.util.TreeSet;
public class BrotherComparator {
Set
public BrotherComparator(String a) {
if (a == null)
set = null;
else {
set = new TreeSet
for (int i = 0; i < a.length(); i++) {
set.add(a.charAt(i));
}
}
}
public Set
return set;
}
public void setSet(Set
this.set = set;
}
public boolean compareBrother(BrotherComparator brother) {
if (brother == null || brother.getSet() == null)
return false;
if (brother == this)
return true;
if (brother.getSet().toString().equals(set.toString()))
return true;
else
return false;
}
public static void main(String[] args) {
BrotherComparator a = new BrotherComparator("abd");
BrotherComparator b = new BrotherComparator("bda");
BrotherComparator c = null;
System.out.println(a.compareBrother(b));
}
}
最后输出结构true;
JAVA 符合这样的数据结构有TreeSet.
- #include
- using namespace std;
- int main()
- {
- char ch[100],ch1[100];
- int a[27],b[27];
- while (cin >> ch >> ch1)
- {
- memset(a,0,27* sizeof ( int ));
- memset(b,0,27* sizeof ( int ));
- int len1 = strlen(ch);
- int len2 = strlen(ch1);
- if (len1 != len2)
- {
- cout<< "不是兄弟字符串" <
- continue ;
- }
- for ( int i=0;i
- {
- a[( int )ch[i] - 97]++;
- }
- for (i=0;i
- {
- b[( int )ch1[i] - 97]++;
- }
- int flag=1;
- for (i=0;i<27;i++)
- {
- if (a[i] != b[i])
- {
- flag=0;
- break ;
- }
- }
- if (flag)
- {
- cout<< "是兄弟字符串" <
- }
- else
- {
- cout<< "不是兄弟字符串" <
- }
- }
- }
#includeusing namespace std; int main() { char ch[100],ch1[100]; int a[27],b[27]; while(cin >> ch >> ch1) { memset(a,0,27*sizeof(int)); memset(b,0,27*sizeof(int)); int len1 = strlen(ch); int len2 = strlen(ch1); if(len1 != len2) { cout<<"不是兄弟字符串"<
如果只有一负数,并且在数组的最后一位。何解?
- 如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。
- #define TABLE_SIZE 256
- int main()
- {
- char string1[1000]= "bad" ;
- char string2[1000]= "adb" ;
- char *pstring1 ;
- char *pstring2 ;
- unsigned int hash_table[TABLE_SIZE] = {0};
- unsigned int index = 0;
- pstring1 = string1;
- pstring2 = string2;
- while (*pstring1){
- hash_table[*pstring1]+=1;
- printf( "%d\r\n" , *pstring1);
- pstring1++;
- }
- while (*pstring2){
- hash_table[*pstring2]-=1;
- printf( "%d\r\n" , *pstring2);
- pstring2++;
- }
- for (index = 0; index < TABLE_SIZE ; index++)
- if (hash_table[index]!=0)
- break ;
- if (index == TABLE_SIZE)
- printf( "%s == %s\r\n" , string1, string2);
- else
- printf( "%s != %s\r\n" , string1, string2);
- getchar();
- return 0;
- }
如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。 #define TABLE_SIZE 256 int main() { char string1[1000]="bad"; char string2[1000]="adb"; char *pstring1 ; char *pstring2 ; unsigned int hash_table[TABLE_SIZE] = {0}; unsigned int index = 0; pstring1 = string1; pstring2 = string2; while(*pstring1){ hash_table[*pstring1]+=1; printf("%d\r\n", *pstring1); pstring1++; } while(*pstring2){ hash_table[*pstring2]-=1; printf("%d\r\n", *pstring2); pstring2++; } for(index = 0; index < TABLE_SIZE ; index++) if(hash_table[index]!=0) break; if(index == TABLE_SIZE) printf("%s == %s\r\n", string1, string2); else printf("%s != %s\r\n", string1, string2); getchar(); return 0; }
public class Test {
/**
* 计算猴子分桃最少数,最后一只猴子不能吃桃,只能带走一个桃子。
* @param ave 最少基数
* @param count 猴子个数
* @param c 分桃次数,每次减1
* @return
*/
public static int split(int ave, int count, int c) {
int t = 1;
if (c != 1)
t = ave * (c) + 1;
System.out.println(c + "->" + t);
c++;
if (c == count + 1) {
return t;
} else {
return split(t, count, c);
}
}
public static void main(String args[]) throws Exception {
System.out.println("mix=" + split(1, 5, 1));
}
}
输入结果:
1->1
2->3
3->10
4->41
5->206
mix=206
#define TABLE_SIZE 256
int main()
{
char string1[1000]="bad";
char string2[1000]="adb";
char *pstring1 ;
char *pstring2 ;
unsigned int hash_table[TABLE_SIZE] = {0};
unsigned int index = 0;
pstring1 = string1;
pstring2 = string2;
while(*pstring1){
hash_table[*pstring1]+=1;
printf("%d\r\n", *pstring1);
pstring1++;
}
while(*pstring2){
hash_table[*pstring2]-=1;
printf("%d\r\n", *pstring2);
pstring2++;
}
for(index = 0; index < TABLE_SIZE ; index++)
if(hash_table[index]!=0)
break;
if(index == TABLE_SIZE)
printf("%s == %s\r\n", string1, string2);
else
printf("%s != %s\r\n", string1, string2);
getchar();
return 0;
}
public class Test {
public static int split(int ave, int count, int c) {
int i = c;
int t = ave * (c++) + 1;
System.out.println(i + "->" + t);
if (c == 6) {
return t;
} else {
return split(t, count, c);
}
}
public static void main(String args[]) throws Exception {
System.out.println("mix=" + split(1, 5, 1));
}
}
肯定基数为1是最少数,既最后一只猴子吃掉一个,最后拿走一个。如果最后一只猴子不能吃,只能拿走那自己考虑了。
输入结果:
1->2
2->5
3->16
4->65
5->326
mix=326
下标0->25对应26个字母,数组的值为每个字符出现的次数,需要每个字符串遍历一遍才能得到特征值,插入特征值时就可以按大小排列成链表,到之后显示链表即可
rand7做10次,然后累加以后对10取模后+1
#include
int a(int num, int split, int eat)
{
if (num == 1)
return num * split + eat;
else
return a(num - 1, split, eat) * split + eat;
}
int main()
{
printf("total: %d\n", a(5, 5, 1));
}
任意一只喝一瓶
任意两只喝一瓶
任意三只喝一瓶
任意四只喝一瓶
任意五只喝一瓶
结果为
c5(1)+c5(2)+c5(3)+c5(4)+c5(5)=31
在7进制下构造一个[0,1) 的随机函数,如下:
random()=(rand7()-1)/7+(rand7()-1)/7*7+(rand7()-1)/7*7*7+(rand7()-1)/7*7*7*7
有了[0,1) 的随机函数,剩下的都好办了
我觉得应该是:
1.两次得到随机数 a1 a2 ;
2.如果 a1*7+a2<48 则 b=(a1*7+a2)/4-1 否则重复第一步;
非常感谢你的思路
取2时可以是1+1、2+0
。。。
所以1-10不等概率。。。
第二题:
( rand7() + rand7() + rand7() + rand7() + rand7() + rand7() + rand7() + rand7() + rand7() + rand7() ) / 7
第三题: unsigned int count[24] ; 统计各个字符出现的次数,然后比较
第四题: IP 地址划分成两段数字,前一部分按照顺序排列,另外一部分按照hash表,在第二部分,最近查找的可以移到前面,没有经验,不知道是个什么规律。
第五题:依据快速排序的思想,排序一次就可以了,设置用来比较的 middle value = 0;
10-70出现的机会必然是中间大,两头小,况且:
10、11、12、13除7取整为1
14、15、16、17、18、19、20除7取整为2
。。。。
1-10每个数机会不是1/10 。。。
1: 28250575
2: 28249980
3: 28248440
4: 28246570
5: 28245085
6: 28244524
7: 28245085
8: 28246570
9: 28248440
10:28249980
- int Array[7]={1,2,3,4,5,6,7};
- int Result[10]={0};
- for ( int a1 = 0;a1<7;a1++ ) //1
- { for ( int a2 = 0;a2<7;a2++) //2
- { for ( int a3 = 0;a3<7;a3++) //3
- { for ( int a4 = 0;a4<7;a4++) //4
- { for ( int a5 = 0;a5<7;a5++) //5
- { for ( int a6 = 0;a6<7;a6++) //6
- { for ( int a7 = 0;a7<7;a7++) //7
- { for ( int a8 = 0;a8<7;a8++) //8
- { for ( int a9 = 0;a9<7;a9++) //9
- { for ( int a10 = 0;a10<7;a10++) //10
- { int k = Array[a1]+Array[a2]+Array[a3]+Array[a4]+Array[a5]
- +Array[a6]+Array[a7]+Array[a8]+Array[a9]+Array[a10];
- k = k%10;
- Result[k]++;
- }}}}}}}}}}
- for ( int j=0; j<10;j++ )
- printf( "\nResult[%d] Count is :%d " ,j,Result[j]);
int Array[7]={1,2,3,4,5,6,7}; int Result[10]={0}; for ( int a1 = 0;a1<7;a1++ )//1 {for (int a2 = 0;a2<7;a2++)//2 {for (int a3 = 0;a3<7;a3++)//3 { for (int a4 = 0;a4<7;a4++)//4 {for (int a5 = 0;a5<7;a5++)//5 {for (int a6 = 0;a6<7;a6++)//6 {for (int a7 = 0;a7<7;a7++)//7 {for (int a8 = 0;a8<7;a8++)//8 {for (int a9 = 0;a9<7;a9++)//9 {for (int a10 = 0;a10<7;a10++)//10 {int k = Array[a1]+Array[a2]+Array[a3]+Array[a4]+Array[a5] +Array[a6]+Array[a7]+Array[a8]+Array[a9]+Array[a10]; k = k%10; Result[k]++; }}}}}}}}}} for ( int j=0; j<10;j++ ) printf("\nResult[%d] Count is :%d ",j,Result[j]);
而楼主发的那种方法显然不太稳定,依赖于rand7()产生两数积少于40,目前我也没找到更好的解决方法。
- //return:negative count
- int xsort( int *data, int size)
- {
- int neg_num = 0;
- int pos_p, neg_p;
- int i, j;
- for (i = 0; i < size; i++) //总的负数个数
- if (data[i] < 0)
- neg_num++;
- int pos_num = 0;
- for (i = 0; i < neg_num; i++)
- if (data[i] >=0)
- pos_num++;
- i = 0, j = size -1;
- pos_p = neg_num;
- neg_p = neg_num - 1;
- while (pos_num > 0){
- while (data[i] < 0) i++; //找正数
- int tmp = data[i];
- int k = i;
- while (k++ < neg_p)data[k-1] = data[k]; //腾出了负数的位置
- while (data[j] >=0)j--; //找负数
- data[neg_p--] = data[j]; //负数搁进去
- k = j;
- while (k-- > pos_p)data[k+1] = data[k]; //腾出了正数的位置
- data[pos_p++] = tmp; //正数搁进去
- pos_num--;
- }
- return neg_num;
- }
//return:negative count int xsort(int *data, int size) { int neg_num = 0; int pos_p, neg_p; int i, j; for(i = 0; i < size; i++)//总的负数个数 if(data[i] < 0) neg_num++; int pos_num = 0; for(i = 0; i < neg_num; i++) if(data[i] >=0) pos_num++; i = 0, j = size -1; pos_p = neg_num; neg_p = neg_num - 1; while(pos_num > 0){ while(data[i] < 0) i++;//找正数 int tmp = data[i]; int k = i; while(k++ < neg_p)data[k-1] = data[k];//腾出了负数的位置 while(data[j] >=0)j--;//找负数 data[neg_p--] = data[j];//负数搁进去 k = j; while(k-- > pos_p)data[k+1] = data[k];//腾出了正数的位置 data[pos_p++] = tmp;//正数搁进去 pos_num--; } return neg_num; }
时间复杂度我觉得是
O(N) //求负数个数
+ O(N) //求pos_num
+ k*( O(N)+O(N)+O(N)+O(N)) //pos_num次大循环中的四次遍历。
= k*O(N);
k为负数的个数前面部分的正数个数pos_num 。
按说k为常数 故 时间复杂度也可以达到要求。
- int n = 0;
- int m = 0;
- int p = -1;
- while (n == 0) {
- m = rand7();
- if (m == 6) {
- p = 0
- }
- else if (m == 7) {
- p = 5;
- }
- else {
- if (p >= 0) {
- n = m + p;
- }
- }
- }
- return n;
int n = 0; int m = 0; int p = -1; while (n == 0) { m = rand7(); if (m == 6) { p = 0 } else if (m == 7) { p = 5; } else { if (p >= 0) { n = m + p; } } } return n;
#include
using namespace std;
bool test(int n)
{
for (int j = 0; j < 5; j++)
{
if ((n - 1)%5 != 0)
{
return false;
}
n = (n - 1)/5 * 4;
}
return true;
}
void main()
{
for (int i = 10; i < 10000; i++)
{
if(test(i))
cout << i << " ";
}
cout << endl;
}
(7-rand7)/(7-1)*(10-1)+1这样应该可以
这是反求0到1随机数,再求1到10随机
引用“xubo115”的评论: 第二题有人解决掉吗??
- private void aa()
- {
- for ( int n = 1; n <= 1000000; n++)
- {
- if (a1(n))
- {
- MessageBox.Show(n.ToString());
- break ;
- }
- }
- }
- private bool a1( int n)
- {
- //第一次
- if ((n-1)%5==0)
- {
- n = ((n - 1) / 5) * 4; //第一次结余数
- if ((n - 1) % 5 == 0)
- {
- n = ((n - 1) / 5) * 4; //第二次结余数
- if ((n - 1) % 5 == 0)
- {
- n = ((n - 1) / 5) * 4; //第三次结余数
- if ((n - 1) % 5 == 0)
- {
- n = ((n - 1) / 5) * 4; //第四次结余数
- if ((n - 1) % 5 == 0)
- {
- n = ((n - 1) / 5) * 4; //第五次结余数
- return true ;
- }
- }
- }
- }
- }
private void aa() { for (int n = 1; n <= 1000000; n++) { if (a1(n)) { MessageBox.Show(n.ToString()); break; } } } private bool a1(int n) { //第一次 if ((n-1)%5==0) { n = ((n - 1) / 5) * 4;//第一次结余数 if ((n - 1) % 5 == 0) { n = ((n - 1) / 5) * 4;//第二次结余数 if ((n - 1) % 5 == 0) { n = ((n - 1) / 5) * 4;//第三次结余数 if ((n - 1) % 5 == 0) { n = ((n - 1) / 5) * 4;//第四次结余数 if ((n - 1) % 5 == 0) { n = ((n - 1) / 5) * 4;//第五次结余数 return true; } } } } }
5x/4+1)5/4+1)5/4+1)5/4+1)5/4+1=y
当x>=1时,即可求出y的值。
没有去算这个值是多少,如觉得此方法不妥,请求指导。
引用“xubo115”的评论: 第一题:3121,代码如下,暂时木有参考其他人,继续下面的题
[code=java]
public ...
- public class peach {
- public static void main(String []args){
- int i,j;
- int n= 6 ;
- for (;;){
- i=n;
- for (j= 1 ;j<= 6 ;j++){
- if ((i- 1 )% 5 == 0 )
- i= (i- 1 )* 4 / 5 ;
- else break ;
- }
- if (j == 6 )
- break ;
- n=n+ 5 ;
- }
- System.out.println( "the min number is " +n);
- }
- }
public class peach { public static void main(String []args){ int i,j; int n=6; for(;;){ i=n; for(j=1;j<=6;j++){ if ((i-1)%5 == 0) i= (i-1)*4/5; else break; } if (j == 6) break; n=n+5; } System.out.println("the min number is "+n); } }
题目没有说明单个字符串内有没有重复,两个串重复个数要不要一致,我现在按重复个数也需要一致处理。
时间复杂度:O(n); n为字符串长度,再次遍历128次是常数,少于O(n),忽略。
空间复杂度:O(1); 固定为128个桶排序原理需要的空间。其他临时变量忽略不计
- bool CItems::CheckBrotherString( char *left, char *right)
- {
- //把键盘128个字符列举,使用桶排序相关原理实现
- char keys[128];
- for ( int i = 0; i<128; i++ )
- {
- keys[i]=0;
- }
- //遍历第一个字符串,记录字符个数
- while ( *left!= '\0' )
- {
- keys[*left++]++;
- }
- //遍历第二个字符串,记录字符个数
- while ( *right!= '\0' )
- {
- keys[*right++]--;
- }
- for ( int i = 0; i<128; i++ )
- {
- if ( keys[i]!=0)
- {
- return false ;
- }
- }
- return true ;
- }
bool CItems::CheckBrotherString(char *left,char *right) { //把键盘128个字符列举,使用桶排序相关原理实现 char keys[128]; for ( int i = 0; i<128; i++ ) { keys[i]=0; } //遍历第一个字符串,记录字符个数 while ( *left!='\0' ) { keys[*left++]++; } //遍历第二个字符串,记录字符个数 while ( *right!='\0' ) { keys[*right++]--; } for ( int i = 0; i<128; i++ ) { if ( keys[i]!=0) { return false; } } return true; }
注:数字溢出先不考虑
但如果用枚举法,算法复杂度?先不用逻辑判断,单单5->3121;粗略算了一下,起码是O(n^3)!
- case 2:
- //m*k%4 need to equal 2
- switch ( m%4 )
- {
- case 1:
- k = 2;
- break ;
- case 2:
- k = 1;
- break ;
- case 3:
- printf( "ERROR!" );
- break ;
- default :
- printf( "ERROR!" );
- break ;
- }
- break ;
- case 3:
- //m*k%4 need to equal 1
- switch ( m%4 )
- {
- case 1:
- k = 1;
- break ;
- case 2:
- printf( "ERROR!" );
- break ;
- case 3:
- k = 7;
- break ;
- default :
- printf( "ERROR!" );
- break ;
- }
- break ;
- default :
- break ;
- }
- return k;
- }
case 2: //m*k%4 need to equal 2 switch ( m%4 ) { case 1: k = 2; break; case 2: k = 1; break; case 3: printf("ERROR!"); break; default: printf("ERROR!"); break; } break; case 3: //m*k%4 need to equal 1 switch ( m%4 ) { case 1: k = 1; break; case 2: printf("ERROR!"); break; case 3: k = 7; break; default: printf("ERROR!"); break; } break; default: break; } return k; }
- int CItems::GetKValue( int y, int m)
- {
- int k=-1;
- //let x = y+m*k;
- //search k st. x is integer
- //y%5=1;make (m*k)%4 = 3
- switch ( y%4 )
- {
- case 0:
- //m*k%4 need to equal 4
- switch ( m%4 )
- {
- case 1:
- case 3:
- k = 4;
- break ;
- case 2:
- k = 2;
- break ;
- default :
- printf( "ERROR!" );
- break ;
- }
- break ;
- case 1:
- //(m*k)%4 need to equal 3
- switch ( m%4 )
- {
- case 1:
- k = 3;
- break ;
- case 2:
- printf( "ERROR!" );
- break ;
- case 3:
- k = 1;
- break ;
- default :
- printf( "ERROR!" );
- break ;
- }
- break ;
int CItems::GetKValue(int y,int m) { int k=-1; //let x = y+m*k; //search k st. x is integer //y%5=1;make (m*k)%4 = 3 switch ( y%4 ) { case 0: //m*k%4 need to equal 4 switch ( m%4 ) { case 1: case 3: k = 4; break; case 2: k = 2; break; default: printf("ERROR!"); break; } break; case 1: //(m*k)%4 need to equal 3 switch ( m%4 ) { case 1: k = 3; break; case 2: printf("ERROR!"); break; case 3: k = 1; break; default: printf("ERROR!"); break; } break;
正确答案
- void CItems::MonkeyAndPeachs()
- {
- //y0-1 = 5*y1/4;
- //y1-1 = 5*y2/4;
- //y2-1 = 5*y3/4;
- //y3-1 = 5*y4/4;
- //y4-1 = 5*y5/4;
- int y = 0;
- //int x = 0;
- int m = 1;
- int k = 0;
- int i;
- for ( i =0;i<5;i++ )
- {
- if ( (k = GetKValue(y,m))<0 )
- {
- printf( "ERROR!" );
- return ;
- }
- //x = y+m*k;
- //y = x*5/4+1;
- y = (y+m*k)*5/4+1;
- m *=5;
- printf( ",%d:%d \n" ,i,y);
- }
- printf( "The result is %d" ,y);
- return ;
- }
void CItems::MonkeyAndPeachs() { //y0-1 = 5*y1/4; //y1-1 = 5*y2/4; //y2-1 = 5*y3/4; //y3-1 = 5*y4/4; //y4-1 = 5*y5/4; int y = 0; //int x = 0; int m = 1; int k = 0; int i; for ( i =0;i<5;i++ ) { if ( (k = GetKValue(y,m))<0 ) { printf("ERROR!"); return ; } //x = y+m*k; //y = x*5/4+1; y = (y+m*k)*5/4+1; m *=5; printf(",%d:%d \n",i,y); } printf("The result is %d",y); return ; }
2只最多判断 4瓶毒药 2^2
3只 8 2^3
1 喝 1357
2 喝 2356
3 喝 4567
如果1 死 2 3 活 则 第1瓶有毒 二进制 也就是 001
如果2 死 1 3 活 则 第2瓶有毒 二进制 也就是 010
如果1 2 死 3 活 则 第3瓶有毒 二进制 也就是 011
如果3 死 1 2 活 则 第4瓶有毒 二进制 也就是 100
如果1 3 死 2 活 则 第5瓶有毒 二进制 也就是 101
如果2 3 死 1 活 则 第6瓶有毒 二进制 也就是 110
如果1 2 3 全死 则 第7瓶有毒 二进制 也就是 111
如果1 2 3 全活 则 第8瓶有毒 二进制 也就是1000
所以5只老鼠可以测2的5次方也就是32瓶
淘宝打折网 www.xflian.com
int rand10() {
int value = 0;
for(int i = 0; i < 10; i++) {
value += rand7();
}
return value % 10;
}
1,1概率是1/36,3,5,35,44,6,2,2,6,你自己对比概率多少吧
#include
void main()
{
int peach_number; //存储分之前的桃子个数
int peach_number1; //存储第1只猴子操作后剩下的桃子个数
int peach_number2; //存储第2只猴子操作后剩下的桃子个数
int peach_number3; //存储第3只猴子操作后剩下的桃子个数
int peach_number4; //存储第4只猴子操作后剩下的桃子个数
for( peach_number=6;peach_number>=6;peach_number++)
{
if((peach_number-1)%5==0)
{
peach_number1=(peach_number-1)*4/5;
if((peach_number1-1)%5==0)
{
peach_number2=(peach_number1-1)*4/5;
if((peach_number2-1)%5==0)
{
peach_number3=(peach_number2-1)*4/5;
if((peach_number3-1)%5==0)
{
peach_number4=(peach_number3-1)*4/5;
if((peach_number4-1)%5==0) //第5只猴子操作后,满足要求就退出循环
break;
}
}
}
}
}
cout<<"桃子至少含有:"<
int rand10()
{
int nResult=0;
while(true)
{
nResult=rand7();
if(nResult<=5)
break;
}
while(true)
{
int n = rand7();
if (n==1)
continue;
else if(n>4)
nResult*=2;
else
nResult=nResult*2-1;
break;
}
return nResult ;
}
我能想到的效率比较高、随机比较平均的算法,用加法和乘法的好像都有问题,因为数值分区间的概率是有问题的
无数瓶无色液体,只有一瓶是毒药
喝了无色液体,五分钟后才会看到结果。
现在五只老鼠,五分钟的时间,问能检测多少瓶液体
1、五只小白鼠分别喝了5瓶无色液体,五分钟过后,其中一只死亡,那么可以确定全部液体,只有一瓶毒药,那么就全部分开来。
2、分别喝了在5分钟后均未死亡,那么只能确定5瓶蒸馏水。
PS:给定的条件是五只老鼠,五分钟的时间,每只老鼠喝了毒药五分钟后才会死亡。
这样至少可以检查大于5瓶的个数。
至少可以检测8瓶。如果要检测到10瓶的,有一定的概率。
一下方法可以一次性检测10瓶。
把10瓶毒药分为4组,前三组各三瓶,最后1组1瓶。
只检测前面三组。
假定三个组分别为A,B,C。
1. 把A,B,C三组中的液体混合,分别给三只老鼠喝。
分别为测试用例 a,b,c
2. 分别从A,B,C组中各取1只液体,混合,给第四只老鼠吃。为测试用例 d
3.分别在从A,B,C组中各取一次液体(第二部取过的,不能在取),混合,给第五只老鼠吃。为测试用例e
这样,不过毒药在那瓶液体都可以在5分钟中一次性得到液体在拿一瓶。
如果 abcde都活着,说明毒药是那瓶没有参加测试的。
如果abcde只有一个死了,说明毒液在在吃参与混合测试一次的那瓶液体中。虽然有三瓶液体只混合了一次测试,但是从死的那只测试编号可以知道是那个组。
如果abcde死了2只,那么交叉也可以得出那瓶是毒液。
- //需要事先知道字符集,假定为26个字母吧
- bool matchbrotherstr( char * str1, char * str2)
- {
- int s1[26] = {0}, s2[26] = {0};
- char *p;
- for (p = str1; *p != NULL;p++)
- s1[*p - 'a' ]++;
- for (p = str2; *p != NULL;p++)
- s2[*p - 'a' ]++;
- for ( int i = 0; i < 26; i++){
- if (s1[i] == s2[i])
- continue ;
- else
- return false ;
- }
- return true ;
- }
//需要事先知道字符集,假定为26个字母吧 bool matchbrotherstr(char* str1, char* str2) { int s1[26] = {0}, s2[26] = {0}; char *p; for(p = str1; *p != NULL;p++) s1[*p -'a']++; for(p = str2; *p != NULL;p++) s2[*p -'a']++; for(int i = 0; i < 26; i++){ if(s1[i] == s2[i]) continue; else return false; } return true; }
其实这题挺难的,应为要实现真正的随机,我想大多数人一开始想的方法都不是随机分布的
- int rand7()
- {
- return rand()%7 + 1;
- }
- int rand10()
- {
- int tmp, mid;
- do {
- mid = rand7();
- } while (mid == 4);
- //50%概率
- if (mid < 4){ //return 1-5
- do {
- tmp = rand7();
- } while (tmp == 1 || tmp == 7);
- return tmp - 1;
- } else { //return 6-10
- do {
- tmp = rand7();
- } while (tmp == 1 || tmp == 7);
- return tmp + 4;
- }
- }
int rand7() { return rand()%7 + 1; } int rand10() { int tmp, mid; do{ mid = rand7(); }while(mid == 4); //50%概率 if(mid < 4){//return 1-5 do{ tmp = rand7(); }while(tmp == 1 || tmp == 7); return tmp - 1; }else{//return 6-10 do{ tmp = rand7(); }while(tmp == 1 || tmp == 7); return tmp + 4; } }
设有n个集合(集合用队列表示)
for(i =0; i < n;++i)
{
取出集合i中的一个元素x并依次和集合i+1到集合n-1比较,
如果x在后面的集合中,则后面的集合与当前集合合并。
合并后n减1.
}
- int _tmain( int argc, _TCHAR* argv[])
- {
- int result = 0;
- while ( true ){
- int a[6];
- a[5] = result*4;
- int i;
- for (i = 4; i >=0; i--){
- if (a[i+1]%4 == 0){
- a[i] = a[i+1]*5/4 + 1;
- continue ;
- }
- break ;
- }
- if (i == -1){
- printf( "%d" , a[0]);
- break ;
- }
- else
- result++;
- }
- return 0;
- }
int _tmain(int argc, _TCHAR* argv[]) { int result = 0; while(true){ int a[6]; a[5] = result*4; int i; for(i = 4; i >=0; i--){ if(a[i+1]%4 == 0){ a[i] = a[i+1]*5/4 + 1; continue; } break; } if(i == -1){ printf("%d", a[0]); break; } else result++; } return 0; }
function rand10()
{
int a = rand7();
int b = rand7();
int c = rand7();
int m = a+b+c;//值是3到21
int n = m-1;//值是2到20
return n/2;
}
3=1+1+1
4=1+1+2=1+2+1=2+1+1 4的概率是3的概率的三倍
5=1+1+3=……
目前觉得
引用“wwq3073135”的评论: 2、while(1){
x=7*(random7()-1) + random7() ;
if(x...[/quote]
的方法比较好
解释见
[quote=chaoyue1216]明白了,确实是 7*(random7()-1) + random7() 生成的数在1到49间均匀分面...
题目没有说明是使用什么方式存储什么样的树,我只以最简单的完全二叉树的方式去计算。
如果不是二叉树又另当别论
- //如果二叉树使用数组顺序存储结构,第一个节点下标是x,第二个节点下标是y;
- //第0个节点不使用,1为根节点,算法如下
- int x =10;
- int y =100;
- while (1)
- {
- if (x==y)
- {
- break ;
- }
- x>y?x/=2:y/=2;
- }
- printf( "The parent is %d" ,x);
//如果二叉树使用数组顺序存储结构,第一个节点下标是x,第二个节点下标是y; //第0个节点不使用,1为根节点,算法如下 int x =10; int y =100; while(1) { if (x==y) { break; } x>y?x/=2:y/=2; } printf("The parent is %d",x);
- int Array[10] = { -1,2,-3,4,-5,6,-7,8,-9,10 };
- int index_front = 0;
- int temp;
- int i;
- int j;
- for ( i = 0; i<10; i++ )
- {
- if (Array[i]<0)
- {
- temp = Array[i];
- for ( j = i;j>index_front; j--)
- {
- Array[j] = Array[j-1];
- }
- Array[index_front] = temp;
- index_front++;
- }
- }
- for ( i = 0; i<10; i++ )
- {
- printf( ", %d" ,Array[i]);
- }
int Array[10] = { -1,2,-3,4,-5,6,-7,8,-9,10 }; int index_front = 0; int temp; int i; int j; for ( i = 0; i<10; i++ ) { if (Array[i]<0) { temp = Array[i]; for ( j = i;j>index_front; j--) { Array[j] = Array[j-1]; } Array[index_front] = temp; index_front++; } } for ( i = 0; i<10; i++ ) { printf(", %d",Array[i]); }
const int monkey = 5;
bool text_last_take(int n)
{
for(int i = 0 ; i < monkey - 1 ; i ++)
{
if((n*5+1)%4 == 0)
{
n =(n*5+1)/4;
continue;
}
return false;
}
return true;
}
int total(void)
{
int last_get = 0 ;
while(! text_last_take(++last_get))
{
if(last_get>1000) return 0;
}
printf("%d\n",last_get);
for(int i = 0 ; i < monkey-1;i++)
{
last_get = (last_get*5+1)/4;
}
return last_get*5+1;
}
int main(int argc, char* argv[])
{
printf("%d\n",total());
return 0;
}
不知道是不是,我是枚举出最后一个猴子拿走的的那一份个数然后回溯上去,最后猴子拿走255个,桃子总是是3121,请高人指点下。
还有楼主,你blog流量高我们都知道
第四题,应该就是用hash表或者树
n是分的堆数,m是分的次数.
{
return rand7() * rand7() %11
}