(搜狗两道笔试题)子数组乘积|等概率发生器

【题目】

鄙视回来,只能说自己平时积累的不够,题目不难
//@1 给定一个长度为N的数组,只允许使用乘法,不能用除法,计算任意N-1个数的乘积
//类似于编程之美上的“需找子数组的最大乘积”,只不过题目要求返回所有乘积,要求时间复杂度是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为止
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
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值