取样
问题:程序的输入包括两个整数m和n,其中m<n;输出是0-n-1范围内m个随机整数的有序列表,不允许重复。
算法1:
int bigRand()
{
return RAND_MAX * rand() + rand();
}
int randint(int l , int u)
{
return l + bigRand() % (u - l + 1);
}
void rand1(int m, int n)
{
int select = m, remaining = n;
for (int i = 0; i < n; i++)
{
if ((bigRand() % remaining) < select)
{
cout << i << "\t"; select--;
}
remaining--;
}
cout << endl;
}
Void genknuth(int m, int n)
{
For(int i = 0; i < n; i++)
{
If((bigrand() % (n-1)) < m)
{
Count << i << “\n”;
M--;
}
}
}
程序实现只需要占用几十个字节的内存,而且可以快速解决问题。但是当n很大的时候,代码运行就是相对较慢。
算法2:
C++中set内元素不重复,集合内元素有序排列(默认升序)
void rand2(int m, int n)
{
set<int> s;
while (s.size() < m)
{
s.insert(bigRand() % n);
}
set<int>::iterator iter;
for (iter = s.begin(); iter != s.end(); iter++)
cout << *iter << "\t";
cout << endl;
}
时间:O(mlogm),改数据结构空间开销较大
算法3:
将数组数据0-n-1的数组顺序打乱,然后将前m个元素顺序输出
void rand3(int m, int n)
{
int *x = new int[n];
for (int i = 0; i < n; i++)
{
x[i] = i;
}
for (int i = 0; i < m; i++)
{
int j = randint(i, n - 1);
int t = x[i];
x[i] = x[j];
x[j] = t;
}
sort(x, x + m);
for (int i = 0; i < m; i++)
cout << x[i] << "\t";
cout << endl;
}
N个元素的存储空间,以及O(n+mlogm)的运行时间
原理:
1.正确理解所遇到的问题:问题的陈述通常就包含了与解决方案有关的想法
2.提炼出抽象问题:简洁,明确的问题陈述不仅可以帮助我们解决当前遇到的问题,还有助于我们把解决方案应用到其他问题中。
3.考虑可能多的解法:很多程序员很快就发现了问题的解决方案,他们只愿意花1分钟的时间思考,然后花一天的时间来写代码,而不是先花1个小时来思考,再用一个小时来写代码。
4.实现一种解决方案:列出几种性能比较好的方案,然后从中选择最佳的。
回顾:改进的余地总是存在的。