N个正整数随机排列

这次我们要生成前N个正整数的一个随机排列

书中给出 三种算法 如下:


前提:需要一个随机数生成函数randInt(begin,end),生成从begin 到 end 的随机数


int randInt(int begin, int end)
{
	int temp;
	temp = begin + (rand() % (end - begin + 1));
	return temp;
}


算法一: 

依次填入a[0]到a[n-1]的数组a,每次都不断调用随机数函数,直到生成的随机不同于已经生成的a[0],a[1],...a[i-1],然后填入a[i];

——时间复杂度为O(N²logN),实现省略,但是时间复杂度分析如下:

每一次成功的概率为(N − i)/N,故每一次需要实验的次数为N/(N − i),然后还要检测与前i个数的不同O(i),后



算法二:

同算法一,但是要保存一个附加的数组,称之为used数组,用来记录随机数是有已经被使用,而不用从前到后一次比较: (貌似又是一个用空间换取时间的例子)

——时间复杂度为O(NlogN),实现如下:

//O(NlogN)
int randInt(int begin, int end)
{
	int temp;
	temp = begin + (rand() % (end - begin + 1));
	return temp;
}

void randomPermutation1(int n)
{
	int *a = new int[n];
	bool *used = new bool[n];
	for (int i = 0; i < n; i++)
		used[i] = true;
	int k = 0;
	for (int i = 0; i < n; ++i) {
		k = randInt(1, n);
		//这里是O(logN)
		while (used[k] == false) {
			k = randInt(1, n);
		}

		used[k] = false;
		a[i] = k;
	}
	cout << "{ ";
	for (int i = 0; i < n; i++)
		cout << a[i] << ",";
	cout << " }";
}


算法三:

依次填写数组a[i]=i+1;然后再次遍历都是让这些数随机交换

——时间复杂度为O(N),实现如下:

void randomPermutation2(int n)
{
	int *a = new int[n];
	for (int i = 0; i < n; ++i)
		a[i] = i + 1;
	//从0开始毫无意义,每次的交换相当于让这个位置取范围内的随机值
	for (int j = 1; j < n; ++j)
		swap(a[j], a[randInt(0, j)]);
	cout << "{ ";
	for (int i = 0; i < n; i++)
		cout << a[i] << ",";
	cout << " }";
}



最后加上主函数main(),不要忽视设置随机数种子:
int main()
{
	//不要每次都设置随机数种子,例如在for里面,那么结果可能相同
	int n;
	cin >> n;
	time_t ts;
	srand((unsigned int)time(&ts));
	randomPermutation1(n); 
	randomPermutation2(n);
	system("pause");
}





  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值