很老的一道面试题,要求下排输出的每个数都是先前上排输入数在下排出现的次数

根据上排给出十个数,在其下排填出对应的十个数
要求下排每个数都是先前上排那十个数在下排出现的次数。
上排的十个数如下:
【0,1,2,3,4,5,6,7,8,9】
举一个例子,
数值: 0,1,2,3,4,5,6,7,8,9
分配: 6,2,1,0,0,0,1,0,0,0
0  在下排出现了 6  次,1  在下排出现了 2  次,
2  在下排出现了 1  次,3  在下排出现了 0  次...

 

据说只给你10分钟时间,尼玛,又被完爆,还让不让人活了。从字面上来看,本题对输入规则没有任何约束,也就是说不能简单推断上排数是从0开始的连续整数,另外,个人觉得如果上排包含重复数字是很麻烦的,因此我只考虑了非重复的情况,描述如下。

输入:规模为n的数组a[n],且a中没有重复数字,也没有负数

输出:数组b[n],要求b[i]是a[i]在b中出现的次数

一开始试图寻找规律,希望能通过推导的方式求解,没搞定。于是转到暴力求解+剪枝的思路上,比较容易想到的剪枝条件有2个,sum(b[i])<=n 且 sum(b[i]*a[i]) <= n,这2个条件都需要a没有重复数字作为前提。另外,可以计算出每个b[i]的取值范围,a[i]*b[i] <= n。最后将遍历出的结果拿去验证正确性,代码如下。

  1 //检查遍历结果的正确性,根据a的每个元素检查b中的值是否正确
  2 static bool checkValid(int a[],int b[], int size)
  3 {
  4     for(int i=0; i < size; ++i)
  5     {                
  6         int cnt =0;
  7         for(int j=0; j < size; ++j)
  8         {
  9             if(b[j] == a[i])
 10             {
 11                 cnt++;
 12             }
 13         }
 14         if(cnt != b[i])
 15         {
 16             return false;
 17         }
 18     }
 19 
 20 
 21     for(int i=0; i < size; ++i)
 22     {
 23         printf("%2d,",a[i]);
 24     }
 25     printf("\n");
 26     for(int i=0; i < size; ++i)
 27     {
 28         printf("%2d,",b[i]);
 29     }
 30     printf("\n");
 31     return true;
 32 }
 33 /*主函数,递归遍历下排数组b的取值,size为输入和输出数组的大小,
 34 currIdx表示当前需要填充b[currIdx],sumB表示当前累积的sum(b[i]),sumAxB表示当前累积的sum(a[i]*b[i]),其中i小于currIdx*/
 35 static bool permutation2(int a[],int b[], int size, int currIdx,int sumB,int sumAxB)
 36 {
 37     bool result=false;
 38     if(size <=0){
 39         return false;
 40     }
 41     if(currIdx == size)//b的排列完成,检查是否ok
 42     {
 43         result = checkValid(a,b,size);
 44         return result;
 45     }
 46 
 47 
 48     //计算b[x]的取值范围,注意防止发生除0
 49     int range = a[currIdx] == 0 ? size-1: size/a[currIdx];
 50     for(int i=0; i <= range; ++i)
 51     {
 52         //if(currSum + i > size ){break;}//少1个剪枝条件会慢的无法忍受
 53         if(sumB + i > size || sumAxB + i*a[currIdx] > size){break;}
 54         b[currIdx] = i;
 55         if(true ==permutation2(a,b,size,currIdx+1,sumB+i,sumAxB + i*a[currIdx]))
 56         {
 57             result = true;
 58         }
 59     }
 60     
 61     return result;
 62 }
 63 
 64 
 65 void testCalcNumCnt()
 66 {
 67     //测试a为从0开始的连续整数
 68     for(int i=0; i < 13; ++i)
 69     {
 70         int b[100], a[100];
 71         for(int j=0; j < i; ++j)
 72         {
 73             a[j] = j;
 74         }
 75         if(permutation2(a,b,i,0,0,0) ==  false)
 76         {
 77             printf("no solution for size %d \n",i);
 78         }
 79     }
 80 
 81     //测试非连续的情况
 82     int a[3][7]={{0,5,2,3,4,7,6},
 83                  {1,2,3,4,5,6,7},
 84                  {1,2,0,3,4,7,6}};
 85     int b[100];
 86     for(int i=0; i < 3;++i)
 87     {
 88         if(permutation2(a[i],b,7,0,0,0) ==  false)
 89         {
 90             printf("no solution\n");
 91         }
 92     }
 93 
 94     int c[2][1]={{1},{2}};
 95     for(int i=0; i < 2;++i)
 96     {
 97         if(permutation2(c[i],b,1,0,0,0) ==  false)
 98         {
 99             printf("no solution\n");
100         }
101     }
102 }

测试结果:

1、测试上排数组a为从0开始的连续整数

a为空,[0],[0~1], [0~2]: no solution
a为[0~3]: 有2个解

 0, 1, 2, 3,
 1, 2, 1, 0,

 0, 1, 2, 3,
 2, 0, 2, 0,

a为[0~4]: 有1个解
 0, 1, 2, 3, 4,
 2, 1, 2, 0, 0,

a为[0~5]:no solution

a从[0~6]开始的解均是1个,且规律很明显b[0]=a[n-4],b[1]=2,b[2]=1,b[n-4]=1,其他b[i]=0,如下
 0, 1, 2, 3, 4, 5, 6,
 3, 2, 1, 1, 0, 0, 0,
 0, 1, 2, 3, 4, 5, 6, 7,
 4, 2, 1, 0, 1, 0, 0, 0,
 0, 1, 2, 3, 4, 5, 6, 7, 8,
 5, 2, 1, 0, 0, 1, 0, 0, 0,
 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 6, 2, 1, 0, 0, 0, 1, 0, 0, 0,
 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
 7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0,
 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
 8, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,

 

2、测试非连续的情况

 0, 5, 2, 3, 4, 7, 6,
 5, 1, 0, 0, 0, 0, 0,


 1, 2, 3, 4, 5, 6, 7,
 0, 0, 0, 0, 0, 0, 0,
 1, 2, 3, 4, 5, 6, 7,
 1, 0, 0, 0, 0, 0, 0,


 1, 2, 0, 3, 4, 7, 6,
 1, 0, 5, 0, 0, 0, 0,
 1, 2, 0, 3, 4, 7, 6,
 2, 1, 3, 1, 0, 0, 0,

 

 1,
 0,
 1,
 1,


 2,
 0,

posted @ 2014-09-29 00:11  _pop  阅读(775)  评论(0编辑  收藏  举报