2015.07.19
1. hulu面试题
【参考】
http://blog.csdn.net/v_july_v/article/details/7974418
http://www.51nod.com/question/index.html#!questionId=642
【100个人,每人头上戴一顶帽子,写有0~99的一个数,数可能重复,每个人都只能看到除自己以外其他人的帽子。每个人需要说出自己的帽子的数,一个人说对就算赢。】
分析:
一、每个人猜数都是相互独立的,不会互相影响
题中只要有一个人对即算赢,那么考虑其对立事件【所有人都没对】,即:100个人,每个人都没猜对自己帽子对应的数,这样每个人说的数都有99种可能(除了自己帽子对应的数外),而每个人猜数独立,因此:
P(输) = P(所有人都猜错) = (99/100)^100
P(赢) = 1 - P(输) = 1 - (99/100)^100【这个数字几乎 = 1】
二、每个人猜数都可以参考其他人帽子上的数字
这时100个人中按照下述的策略必定有人会猜对。
解析:100个人编号为0-99,每个人可看到其他人帽子上的数。
对于编号为 i 人,将其他人帽子上的数累加
然后mod 100,设余数结果为k
则这个人猜自己帽子上的数为(i - k + 100) mod 100 即可。
注:所有帽子数字累加和 mod 100的结果取值为0 - 99。
2. 搜狗面试题
一个长度为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]的积。
程序要求:
要求具有线性复杂度。
不能使用除法运算符。
分析:
由于不能使用除法,因此不能考虑循环2次的算法(而且此时的时间复杂度也不是线性的)
可以按照以下思路考虑:
定义临时数组,从右至左存储对应数组后面所有元素的乘积;
e.g:
a[0-N-1] 临时数组为temp[0-N-1]
temp[N-1]=a[N-1]
temp[N-2]=a[N-1]
temp[N-3]=a[N-1]*a[N-2]
...
temp[1] = a[N-1]*a[N-2]*...*a[2]
temp[0] = a[N-1]*a[N-2]*...*a[1]
接下来对原数组从左向右遍历,并定义一个临时变量tmp(保存的是原数组当前元素及前面所有元素的乘积)
而temp数组保存的是原数组当前元素后面所有的元素,两者相乘即可得除当前元素外所有元素的乘积。
实现代码如下:
#include <iostream> using namespace std; void printArr(int* a, int len) { for (int i = 0; i < len; ++i) { cout<<a[i]<<" "; } cout<<endl; } void updateArr(int* a, int len) { int* temp = new int[len]; int tmp; temp[len - 1] = a[len - 1]; temp[len - 2] = a[len - 1]; for (int i = len - 3; i >= 0; --i) { temp[i] = a[i + 1] * temp[i + 1]; } tmp = a[0]; a[0] = temp[0]; for (int i = 1; i < len - 1; ++i) { temp[i] *= tmp; tmp *= a[i]; a[i] = temp[i]; } a[len - 1] = tmp; } int main(void) { int a[] = {1, 2, 3, 4, 5, 3}; int len = sizeof(a) / sizeof(int); updateArr(a, len); printArr(a, len); return 0; }