百度面试的一道概率方面算法题
题:
给你一个字符串(可能有几亿个字符),给定一个特殊的字符'a',再给定一个可以产生0和1的随机数发生器,然后让你写一个函数,等概率地返回'a'的一个索引(就是'a'在字符串中的位置,比如字符串为 aaba,那么a的索引为{0, 1, 3},等概率地返回0、1或者3)
想:
最简单的想法:这个如果产生随机数,再把该随机数哈希到字符串长度范围内,再把得到的哈希值作为下标去看对应的字符满足不满足条件,满足条件则返回下标,不满足条件的话重新随机。缺点——如果满足条件的字符很少,那么完全不靠谱!
稍微容易想到的方法:遍历这个字符串,对满足条件的下标建立索引,然后根据索引大小产生随机数,随机访问索引,返回索引所对应的下标值。这个可以有,但是也有明显缺点——如果满足条件的字符很多,那么索引很大,占用大量存储!
最后就是完美的解答了:
答:
#include <sstream>
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
int given_rand()
{
return rand() % 2;
}
unsigned int my_rand()
{
int i, result;
for( i = 0, result = 0 ; i < 32 ; i++ )
{
result <<= 1;
result += given_rand();
}
return result;
}
int main()
{
int index = 0, cnt = 0;
stringstream strstring("aabbbaaabbbbabbbbabbbbbbbbbbbaabbbbbbbbbbbbbbbbbbbbabaaaabbbbbbbbbbbbbbaaabbbbbbbbbbbb");
int ret = 0;
char c;
srand(time(NULL));
while (strstring >> c)
{
index++;
if (c == 'a') {
++cnt;
int rr = my_rand() % (cnt);
if (rr < 1)
ret = index;
}
}
cout << ret;
return 0;
}
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
int given_rand()
{
return rand() % 2;
}
unsigned int my_rand()
{
int i, result;
for( i = 0, result = 0 ; i < 32 ; i++ )
{
result <<= 1;
result += given_rand();
}
return result;
}
int main()
{
int index = 0, cnt = 0;
stringstream strstring("aabbbaaabbbbabbbbabbbbbbbbbbbaabbbbbbbbbbbbbbbbbbbbabaaaabbbbbbbbbbbbbbaaabbbbbbbbbbbb");
int ret = 0;
char c;
srand(time(NULL));
while (strstring >> c)
{
index++;
if (c == 'a') {
++cnt;
int rr = my_rand() % (cnt);
if (rr < 1)
ret = index;
}
}
cout << ret;
return 0;
}