谷歌八道面试题

本文解析了谷歌面试中的经典问题,包括算法设计、随机抽样、数学逻辑等方面,提供了详细的解答思路及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

谷歌八道面试题

1. 正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项,例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12
(1)、设计一个函数void generate(int a,int b,int N ,int * Q)计算Q的前几项
(2)、设计测试数据来验证函数程序在各种输入下的正确性。
解:
void generate(int a, int b, int N, int * Q)  
{  
    int num = 0; //计数  
    int index = 1;   
    while (num < N)  
    {  
        if ((index%a == 0) || ( index%b == 0)) //若index满足条件。放到数组Q  
        {  
            Q[num++] = index;  
        }  
        index++;  
    }  
}  

2. 有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在答谢字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型void proc(char *str) 也可以采用你自己熟悉的语言。
解:
void proc(char *str)  
{  
    assert(str != NULL);  
    int length = strlen(str);  
    char *begin = str;  
    char *end = str + length - 1;  
    while(begin < end)  
    {  
        while (islower(*begin))  
            begin++;  
        while (isupper(*end))  
            end--;  
        char temp = *begin;  
        *begin = *end;  
        *end = temp;  
        begin++;  
        end--;  
    }  
}  

3. 如何随机选取1000个关键字?
给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)。如何才能从这个无穷尽的流中随机的选取1000个关键字?
解:
这是一道蓄水池问题。
定义长度为1000的数组。
对于数据流中的前1000个关键字,显然都要放到数组中。
对于数据流中的的第n(n>1000)个关键字,我们知道这个关键字被随机选中的概率为 1000/n。所以我们以 1000/n 的概率用这个关键       字去替换数组中的随机一个。这样就可以保证所有关键字都以 1000/n的概率被选中。
对于后面的关键字都进行这样的处理,这样我们就可以保证数组中总是保存着1000个随机关键字。
4. 判断一个自然数是否是某个数的平方,当然不能用开方。
解:
假设待判断的数字是 N。
方法1:
遍历从1到N的数字,求取平方并和N进行比较。
如果平方小于N,则继续遍历;如果等于N,则成功退出;如果大于N,则失败退出。
复杂度为O(n^0.5)。
方法2:
使用二分查找法,对1到N之间的数字进行判断。
复杂度为O(log n)。
方法3:
由于
(n+1)^2 
=n^2 + 2n + 1,
= ...
= 1 + (2*1 + 1) + (2*2 + 1) + ... + (2*n + 1)
注意到这些项构成了等差数列(每项之间相差2)。
所以我们可以比较 N-1, N - 1 - 3, N - 1 - 3 - 5 ... 和0的关系。
如果大于0,则继续减;如果等于0,则成功退出;如果小于 0,则失败退出。
复杂度为O(n^0.5)。不过方法3中利用加减法替换掉了方法1中的乘法,所以速度会更快些。
5. 给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。
解:这道题属于等概率随机函数。
1 int rand7() {
2   do {
3     int k = 5 * (rand5() - 1) + rand5() - 1;
4   } while (k >= 21);
5   return (k % 7) + 1;
6 }

6. 1024!某尾有多少个0?
末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数,所以我们只需统计因子5的个数。
是5的倍数的数有: 1024 / 5 = 204个
是25的倍数的数有:1024 / 25 = 40个
是125的倍数的数有:1024 / 125 = 8个
是625的倍数的数有:1024 / 625 = 1个
所以1024! 中总共有204+40+8+1=253个因子5。
也就是说1024! 末尾有253个0。 
7.有5个海盗,按照等级从5到1排列。最大的海盗有权提议他们如何分享100枚金币。但其他人要对此表决,如果多数反对,那他就会被杀死。他应该提出怎样的方案,既让自己拿到尽可能多的金币又不会被杀死? 
解:答案为 98,0,1,0,1
你反向思考就行了,从倒数第2个开始。 
给人员编号 
1,2,3,4,5 

5 我要是能拿到1个就满足了 
4 当然是 100%了,因为自己肯定是支持,,所以5 关心自己能拿到至少一个金币的方案 
3 99个给5一个,这样5肯定会支持,否则4就会拿到所有的,他就一个都拿不到了。4则关心自己能拿到金币的方案 
2 99个,给4一个,这样2:2, 4如果不支持,就只能一个都拿不到,所以会支持你。而3和5则关心能拿到一个的方案 
1 需要2个支持,给3和5,他们肯定会支持,否则他们将一个都拿不到。 

扩展题:有5个海盗,按照等级从5到1排列。最大的海盗有权提议他们如何分享100枚金币。但其他人要对此表决,如果方案得到超过半数的人同意,则按照他的方案进行,否则那他就会被杀死。他应该提出怎样的方案,既让自己拿到尽可能多的金币又不会被杀死? 
解:答案为97,0,1,2,0或者97,0,1,0,2.
5 不说了,就他一个人了 
4 无论怎么分,5都会反对,所以他为了活命,必须支持3号的任何分发,否则就会因为无法得到半数以上的支持而死掉 
3 自己100,因为4 肯定会支持他,所以会被通过,4和5则关心能否拿到一个的方案 
2 无论怎么分,3都会反对,所以他必须给4和5每个人一个,否则他们任何一个人反对,都会被杀 98,0,1,1,而3则关心自己能拿到一个的方案,而4,5则关心能拿到2个的方案,因为他们肯定能拿到一个。
1 需要得到2个支持,从利益最大化看,可以给3号1个,给4或者5号2个,97,0,1,2,0 或者 97,0,1,0,2 
3肯定支持,否则2号分配,他啥都得不到 
4/5肯定支持,否则2分配,他们最多拿到一个。

8. 

Google2009华南地区笔试题

给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含),
指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

比如,A=[1,0] K=21 那么输出结构应该为100。

解:【参考来源:http://blog.youkuaiyun.com/hanchengxi/article/details/9350269

/*
问题:
给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含),
指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

思路:
  1.将数组A排序.
  2.生成一个十个数的数组B,B[i]中的每一个的元素都是A中比i大的最小的元素,如果不在A中则用A中所组合而成的最小的两位数代替,比如上例则生成B[]={1, 3, 3, 8, 8, 8, 8, 8, 10, 10}
  3.从给定的数最高位开始找到第一不在A中的位数i的权值m, 从第i位开始到最高位找到第一个权值m,B[m] != max(A中组合而成的最小的两位数), 剩下的位都用A[0]代替。
  代码如下:
*/
#include<stdio.h> 
#include<stdlib.h> 
#define N 10 
int max = 0; 
int get_number(int *, int *, int ,int); 
int is_in(int *, int , int); 
int main() { 
	int A[] = {2, 3}; 
	int i, j; 
	int *B =NULL; 
	int number = 24; 
	int temp = 0; 
	int result = 0; 
	int count = sizeof(A)/sizeof(int); 

	//对数组A进行排序
	for (i = 0; i < count -1; i++) { 
		for (j = i ; j < count -1; j++) { 
			if (A[j] > A[j + 1]) {
				temp = A[j]; 
				A[j] = A[j + 1]; 
				A[j + 1] = temp; 
			} 
		} 
	} 
<span style="white-space:pre">	//求出数值最小的两位数max</span>
	if (A[0] != 0) { 
		max = A[0] * 11; 
	} else { 
		max = A[1] * 10; 
	} 

	B = (int *)malloc(sizeof(int)*10); 
	if (!B) { 
		printf("out of space\n"); 
		exit(0); 
	} 

	j = i = 0; 
	while (i < count && j < N) { 
		if (A[i] > j) { 
			B[j] = A[i]; 
			j ++; 
		} else { 
			i++; 
		} 
	} 

	while (j < N) { 
		B[j] = max; 
		j++; 
	} 

	for (i=0; i<10; i++) {
		printf("%d ", B[i]);
	}
	printf("\n");
	result = get_number(A, B, number, count); 
	printf("the answer is %d\n", result); 
	return 0; 
}

int get_number(int *A, int* B, int number, int count) { 
	int bit = 0; 
	int i = 0; 
	int temp = number; 
	int j, sum; 
	j = sum = 0; 
	while (temp) { 
		bit++; 
		temp /= 10; 
	} 
	int *p = (int *) malloc(sizeof(int)*bit); 
	if (!p) { 
		printf("out of space\n"); 
		exit(-1); 
	} 
	temp = number; 
	i = 0; 
	while(temp) {
		p[i] = temp % 10;
		temp = temp/10; 
		i ++; 
	} 

	for (i = bit -1; i > 0; i--) {
		if (!is_in(A, p[i], count)) {
			break; 
		} 
	} 

	for (j = i; j < bit; j++) {
		if (max != B[p[j]]) {
			p[j] = B[p[j]]; 
			printf("p[%d] :%d\n", j, p[j]); 
			break; 
		} 
	} 
	if (j == bit) { 
		p[--j] = max; 
	} 
	while (--j >= 0) {
		p[j] = A[0]; 
	} 
	for (i = bit - 1, sum = 0; i >= 0; i--) {
		sum = sum *10 + p[i]; 
	} 
	free(p); 
	return sum; 
} 
int is_in(int *A, int number, int count) {
	int i = 0; 
	int j = count - 1; 
	int mid = 0; 
	while (i <= j) { 
		mid = (i + j)/2; 
		if (A[mid] < number) {
			i = mid + 1; 
		} else if (A[mid] > number) {
			j = mid - 1; 
		} else {
			return 1; 
		} 
	} 
	return 0; 
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值