【题目】
鄙视回来,只能说自己平时积累的不够,题目不难
//@1 给定一个长度为N的数组,只允许使用乘法,不能用除法,计算任意N-1个数的乘积
//类似于编程之美上的“需找子数组的最大乘积”,只不过题目要求返回所有乘积,要求时间复杂度是O(N)
//类似于编程之美上的“需找子数组的最大乘积”,只不过题目要求返回所有乘积,要求时间复杂度是O(N)
void SubMultiply(int *array, int len, int *result)
{
int i;
int *forward_res = new int[len];//forward[i]表示i(不含i)之前的所有数的乘积
int *backward_res = new int[len];//backward[i]表示i之后所有数的乘积
for (i = 1, forward_res[0] = 1; i < len; i++)
{
forward_res[i] = forward_res[i-1]*array[i-1];
}
for (i = len-2, backward_res[len-1] = 1; i>=0; i--)
{
backward_res[i] = backward_res[i+1]*array[i+1];
}
for (i = 0; i < len; i++)
{
result[i] = forward_res[i]*backward_res[i];
}
delete []forward_res;
delete []backward_res;
forward_res = NULL;
backward_res = NULL;
//这样需要从头到尾和从尾到头扫描两次,然后再根据result[i]等于它之前的数和它之后数的乘积就可以
}
//@2大概意思是已知随机函数old_rand(),以p的概率产生0,以1-p的概率产生1,
//现在要求设计一个新的随机函数newRand(),使其以等概率生成1和0
int old_rand()
{
return rand()%2;
}
int new_rand()
{
int first_bit = old_rand();
int second_bit = old_rand();
if (first_bit == 1 && second_bit == 0)
return 1;
else if (first_bit == 0 && second_bit == 1)
return 0;
else
return new_rand();
}
【扩展|思考】
第一道题目编程之美上的是要寻找最大的乘积,这个更简单。
第二道题目可以扩展的地方有
//@3 如果要生成N个独立事件,按照上面思路,应该有(P^x)*((1-P)^y)
//或者可以这样实现,在new_rand()产生等概率0和1的基础上,需找一个最小的k,使得2^k>=N,这样产生一个
//K位的等概率数,在产生的数大于N的时候丢弃,直到小于等于K为止
//或者可以这样实现,在new_rand()产生等概率0和1的基础上,需找一个最小的k,使得2^k>=N,这样产生一个
//K位的等概率数,在产生的数大于N的时候丢弃,直到小于等于K为止
int multi_bit_rand(const int range)
{
int temp = range;
int data_temp = 0;
short bit = 0;
while(temp)
{
bit++;
temp /= 2;
}
while(bit--)
data_temp = data_temp*2 + new_rand();
if (data_temp >= range)
return multi_bit_rand(range);
return data_temp;
}
//@4另一个问题:http://hp.dewen.org/?p=469
//一、要求
//1、产生一个比较大的随机数。
//2、产生的随机数在随机范围内等概率。
//探讨过程很容易,略去,最终采用的方式是组合法+丢弃法
//组合法保证在一个大范围内产生随机数,丢弃法保证在超过随机范围以外的数丢弃,使得以内的数等概率
//组合法是通过每位都产生随机的0~9,进而组合起来的数也是随机的
//比如我要产生51782范围以内的随机数,第一步,组合法,51782有5位,首先按位产生99999以内的数字
//然后再将大于51782的数丢弃就行了
int my_rand()
{
return rand()%10;//产生0~9内的随机数
}
int any_range_rand(const int range)
{
short bit = 0;
int temp_data = 0;
int temp = range;
while(temp)
{
bit++;
temp /= 10;
}
while(bit--)
temp_data = temp_data*10 + my_rand();
if (temp_data >= range)
return any_range_rand(range);
return temp_data;
}
//@5 给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一样。
//现要求使用该函数构造函数rand7(),使函数rand7()可以随机等概率的生成1-7的整数。
//思路:将rand5()函数产生的数字看成五进制,产生两位,这样数据范围就是1~25且等概率
//将1~21的数据保存,对应着1~7,其余丢弃即可实现
int rand5()
{
return any_range_rand(4)+1;
}
int rand7()
{
int tmp;
do
{
tmp = (rand5()-1)*5+rand5();
} while (tmp > 21);
return 1 + tmp % 7;
}
【测试】
分别对等概率0 1,0~N等概率(N取5),以及由rand5() ->rand7()测试
#include <iostream>
using namespace std;
int main()
{
#if 0
while(1)
{
long count = 0;
for (int i = 0; i < 1000000; i++)
{
if (new_rand() == 1)
count++;
}
cout<<"rate :"<<(count)/(double)1000000<<endl;
}
#endif
#if 0
while(1)
{
long count_2 = 0;
int res;
long count_array[5] = {0};
for (long i = 0; i < 100000; i++)
{
res = multi_bit_rand(5);
count_array[res]++;
}
for (int j = 0; j < 5; j++ )
{
cout<<j<<" 概率 :"<<count_array[j]/(double)(100000)<<endl;
}
}
#endif
#if 1
while(1)
{
int res_2;
long count_array_2[7] = {0};
for (long i = 0; i < 100000; i++)
{
res_2 = rand7();
count_array_2[res_2-1]++;
}
for (int j = 0; j < 7; j++ )
{
cout<<j+1<<" 概率 :"<<count_array_2[j]/(double)(100000)<<endl;
}
}
#endif
}