现在的位置: 首页 > 综合 > 正文

2011 google校园招聘试题

2014年07月09日 ⁄ 综合 ⁄ 共 5342字 ⁄ 字号 评论关闭

1、已知两个数字为1~30之间的数字,甲知道两数之和,乙知道两数之积,甲问乙:“你知道是哪两个数吗?”乙说:“不知道”。乙问甲:“你知道是哪两个数吗?”甲说:“也不知道”。于是,乙说:“那我知道了”,随后甲也说:“那我也知道了”,这两个数是什么?

答:1和4 或者1和7

2、一个环形公路,上面有N个站点,A1, ..., AN,其中Ai和Ai+1之间的距离为Di,AN和A1之间的距离为D0。
高效的求第i和第j个站点之间的距离,空间复杂度不超过O(N)
它给出了部分代码如下:
#define N 25
double D[N] 
....
void Preprocess()
{
     //Write your code1;
}
double Distance(int i, int j)
{
      //Write your code2;
}

  1. const int N = 10;  
  2. int D[N];  
  3.   
  4. int A1toX[N];  
  5.   
  6. void Preprocess()  
  7. {  
  8.     srand(time(0));  
  9.   
  10.     for (int i = 0; i < N; ++i)  
  11.     {  
  12.         D[i] = (rand()/(RAND_MAX+1.0)) * N;  
  13.     }  
  14.   
  15.     A1toX[1] = D[1];     //from A1 to A2  
  16.     for (int i = 2; i < N; ++i)  
  17.     {  
  18.         A1toX[i] = A1toX[i-1] + D[i];    //distance from A1 to each point  
  19.     }  
  20.     A1toX[0] = A1toX[N-1] + D[0];    // total length  
  21. }  
  22.   
  23. int distance(int i, int j)  
  24. {  
  25.     int di = (i == 0) ? 0 : A1toX[i-1];  
  26.     int dj = (j ==0) ? 0 : A1toX[j-1];  
  27.     int dist = abs(di - dj);  
  28.     return dist > A1toX[0]/2 ? A1toX[0] - dist : dist;  
  29. }  
  30.   
  31. int main(void)  
  32. {  
  33.     Preprocess();  
  34.     for (int i = 0; i <N; ++i)  
  35.     {  
  36.         cout<<D[i]<<" ";  
  37.     }  
  38.     cout<<endl;  
  39.     for (int i = 1; i <= N; ++i)  
  40.     {  
  41.         cout<<"distance from A1 to A"<<i<<": "<<distance(1, i)<<endl;  
  42.     }  
  43.     return 0;  
  44. }  

3、 一个字符串,压缩其中的连续空格为1个后,对其中的每个字串逆序打印出来。比如"abc   efg  hij"打印为"cba gfe jih"。

  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<stack>  
  4. #include<string>  
  5. using namespace std;  
  6.   
  7. string reverse(string str)  
  8. {  
  9.     stack<char> stk;  
  10.     int len = str.length();  
  11.     string ret = "";  
  12.   
  13.     for (int p = 0, q = 0;p < len;)  
  14.     {  
  15.         if (str[p] == ' ')  
  16.         {  
  17.             ret.append(1,' ');  
  18.             for (q = p; q < len && str[q] == ' '; q++)  
  19.             {}  
  20.             p = q;  
  21.         }  
  22.         else  
  23.         {  
  24.             for (q = p; q < len && str[q] != ' '; q++)  
  25.             {  
  26.                 stk.push(str[q]);  
  27.             }  
  28.             while(!stk.empty())  
  29.             {  
  30.                 ret.append(1,stk.top());  
  31.                 stk.pop();  
  32.             }  
  33.             p = q;  
  34.         }  
  35.     }  
  36.     return ret;  
  37. }  
  38. int main(void)  
  39. {  
  40.     string s = "abc def   ghi";  
  41.     cout<<reverse(s).c_str()<<endl;  
  42.     return 0;  
  43. }   

4、将一个较大的钱,不超过1000000(10^6)的人民币,兑换成数量不限的100、50、10、5、2、1的组合,请问共有多少种组合呢?(完全背包)(其它选择题考的是有关:操作系统、树、概率题、最大生成树有关的题,另外听老梦说,谷歌不给人霸笔的机会。)。

第一种方法(母函数):

  1. #define NUM 7  
  2. int money[NUM] = {1, 2, 5, 10, 20, 50, 100};  
  3.   
  4. // 母函数解法  
  5. int NumOfCoins(int value)  
  6. {  
  7.     int i , j , k , c1[1010] , c2[1010];  
  8.     for(i = 0 ; i <= value ; ++i)  
  9.     {  
  10.         c1[i] = 1;  
  11.         c2[i] = 0;  
  12.     }  
  13.     //第一层循环是一共有 n 个小括号,而刚才已经算过一个了     
  14.     // i 就是代表的母函数中第几个大括号中的表达式   
  15.     for(i = 1 ; i < NUM ; ++i)  
  16.     {  
  17.         for(j = 0 ; j <= value ; ++j)   //j 就是指的已经计算出的各项的系数  
  18.         {  
  19.             for(k = 0 ; k+j <= value ; k += money[i])  //k 就是指将要计算的那个括号中的项  
  20.                 c2[k+j] += c1[j];  
  21.         }  
  22.         for(j = 0 ; j <= value ; ++j)  // 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项  
  23.         {  
  24.             c1[j] = c2[j];  
  25.             c2[j] = 0;  
  26.         }  
  27.     }  
  28.     return c1[value];  
  29. }  


第二种方法(动态规划):
我们可以将它形式化为:


硬搜的话肯定是可以出结果的,但时间复杂度太高。
第一种方法:
设 F[n] 为用那么多种面值组成 n 的方法个数。则 F[n] 可以分成这样互不重复的几个部分:
只用 50 及以下的面值构成 [n] + 0 张 100
只用 50 及以下的面值构成 [n-100] + 1 张 100
只用 50 及以下的面值构成 [n-200] + 2 张 100
……
也就是说,按 F[n] 的组成方案中 100 的张数,将 F[n] 划分成若干等价类,等价类的划分要不重复、不遗漏。这些等价类恰好完整覆盖了 F[n] 的所有情况。
然后对于 50 及以下的方案又可以按 50 的张数划分等价类。于是像这样一层一层递归下去……就可以得到结果了。
把上面的递归过程反过来,从下往上递推,这就是动态规划了。代码(用到了一些 C99 特性,比如栈上的可变长数组):
时间复杂度 < O(N^2)

  1. #define NUM 7  
  2. int money[NUM] = {1, 2, 5, 10, 20, 50, 100};  
  3. // 动态规划解法  
  4. int NumOfCoins(int value)  
  5. {  
  6.     int i , j , t , dp[7][1010];  
  7.     for(i = 0 ; i <= value ; ++i)  //用第0张,即面值为1元的都只有一种
  8.         dp[0][i] = 1;  
  9.   
  10.     for(i = 1 ; i < NUM ; ++i)  
  11.     {  
  12.         for(j = 0 ; j <= value ; ++j)  
  13.         {  
  14.             t = j;  
  15.             dp[i][j] = 0;  
  16.             while(t >= 0)  
  17.             {  
  18.                 dp[i][j] += dp[i-1][t];  //这里必须是d[i-1][j],此时就不包含j
  19.                 t -= money[i];  //减一次表示用了一张money[i]
  20.             }  
  21.         }  
  22.     }  
  23.     return dp[6][value];  
  24. }  


其中 dp[i][j] 表示只用第 i 张面值及以下构成 j 用多少种方法。
改进如下:
a[6][n] = ar[6][n-100]     // 至少包含 1 张 100 的拆分个数
              + ar[5][n]         // 不包含 100 的拆分个数

直接把时间复杂度从 O(n^2) 降到了 O(n):

  1. #define NUM 7  
  2. int money[NUM] = {1, 2, 5, 10, 20, 50, 100};  
  3. // 动态规划解法(完全背包)  
  4. int NumOfCoins(int value)  
  5. {  
  6.     int i , j , dp[7][1010];  
  7.     for(i = 0 ; i <= value ; ++i)
     //用第0张,即面值为1元的都只有一种
  8.         dp[0][i] = 1;  
  9.   
  10.     for(i = 1 ; i < NUM ; ++i)  
  11.     {  
  12.         for(j = 0 ; j <= value ; ++j)  
  13.         {  
  14.             if(j >= money[i])
     //i表示当前的物品算进去;i-1表示当前的物品没有算进去
  15.                 dp[i][j] = dp[i][j - money[i]] + dp[i - 1][j];  
  16.             else  
  17.                 dp[i][j] = dp[i-1][j];  
  18.         }  
  19.     }  
  20.     return dp[6][value];  
  21. }  

或者使用滚动数组也是可以的

  1. #define NUM 7    
  2. int money[NUM] = {1, 2, 5, 10, 20, 50, 100};   
  3. int f[1010] , bf[1010];  
  4. // f[j] == f[i][j]   bf[j] == bf[i-1][j]  
  5. int NumofCoin2(int value)  
  6. {  
  7.     int i , j;  
  8.     for(j = 0 ; j <= value ; ++j)  
  9.         f[j] = 0 , bf[j] = 0;  
  10.     bf[0] = 1;  
  11.   
  12.     for(i = 0 ; i < NUM ; ++i)  
  13.     {  
  14.         for(j = 0 ; j <= value ; ++j)  
  15.         {  
  16.             if(j >= money[i])  
  17.                 f[j] = f[j-money[i]] + bf[j];  
  18.             else  
  19.                 f[j] = bf[j] ;  
  20.         }  
  21.   
  22.         for(j = 0; j <= value ; ++j)  
  23.             bf[j] = f[j] , f[j] = 0;  
  24.     }  
  25.     return bf[value];  
  26.   
  27. }  

抱歉!评论已关闭.