怎样将从1-200的数字完全打乱,但不许重复。

大可山人
博客专家认证
2005-11-30 02:34:34
怎样将从1-200的数字完全打乱,但不许重复。
------------------------------------------
比如:
原来的顺序是:1 2 3 4 5... 200
打乱后的顺序可能是:188 156 2 9 32 34 67 ....(共200个数字,只是顺序杂乱无章)

最好保持较高的执行效率。
...全文
1551 34 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
supesa 2005-12-02
  • 打赏
  • 举报
回复
private void Form1_Load(object sender, System.EventArgs e)
{
int[] st1=new int[20000];
for(int i=0;i<20000;i++)
{
st1[i]=i+1;
}
DateTime dtStart=DateTime.Now;
st1=RandomSort(st1);
DateTime dtEnd=DateTime.Now;
TimeSpan ts=dtEnd-dtStart;
StringBuilder sb=new StringBuilder();
foreach(int i in st1)
{
sb.Append(i);
}
textBox2.Text=sb.ToString();
textBox1.Text=ts.ToString();

}
private int[] RandomSort(int[] arr)
{
SortedList sl=new SortedList();
Random rad=new Random();
foreach(int i in arr)
{
int ikey;
do
{
ikey=rad.Next(1000000000);
}while(sl.ContainsKey(ikey));

sl.Add(ikey,i);
}
int count=0;
foreach(object o in sl.Keys)
{
arr[count]=int.Parse(sl[o].ToString());
count++;
}
return arr;
}
20000条生成速度是0.5秒,应该满足要求
supesa 2005-12-02
  • 打赏
  • 举报
回复
我的算法:如果有1-n的数需要处理,先随机生成n个随机数,然后一一和原数据对应(键为随机数,值为原数据).比如存放在sortedlist中
然后把键排序(sortedlist是按照健排序的,所有如果用sortedlist就不用这步了)
然后按照索引的顺序取出就可以了.
bomb_boy 2005-12-02
  • 打赏
  • 举报
回复
洗牌原理就行了,随即洗个8-9次全乱了,没有必要循环200次
liangpz_2000 2005-12-02
  • 打赏
  • 举报
回复
这个算法在经济适用房摇号系统中可以使用,楼主赶紧给我加分
liangpz_2000 2005-12-02
  • 打赏
  • 举报
回复
经过分布统计确定,1-200在各位置上出现的概率是平均分布
public static int GetRandomSeed()
{
byte[] rndBytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(rndBytes);
return BitConverter.ToInt32(rndBytes,0);
}
public static int[] GetRandomSort(int[] arr)
{
int k = arr.Length; // 要保存的位置
Random rad=new Random(GetRandomSeed());
for( int i = 0; i < k-1; i++ ) // 执行N-1次循环,随机产生要被打乱的数据所在的位置
{
int idx = rad.Next(0,k-i);
// 交换数据
int n = arr[idx];
arr[idx] = arr[k-i-1];
arr[k-i-1] = n;
}
return arr;
}
MSN:liangpz_2000@hotmail.com QQ:18692679
大可山人 2005-12-02
  • 打赏
  • 举报
回复
个人觉得使用:
do
{
ikey=rad.Next(1000000000);
}
while(sl.ContainsKey(ikey));
语句后效率会降低,因为需要遍历搜索。
zpingy 2005-12-01
  • 打赏
  • 举报
回复
johnsuna(缘来是e) 的想法很好,可以考虑空间换时间的办法
givenchy 2005-12-01
  • 打赏
  • 举报
回复
问题在于你所指的杂乱无章的程度是怎样定义的。
举例来说,只要是不连续的数列,就符合你所说的条件。
生成 1、3、5...199、2、4、6...200这样的序列,效率又是多高呢。
自然框架 2005-12-01
  • 打赏
  • 举报
回复
其实很简单了。

想一想平时玩扑克的时候是怎么洗排的就可以了。

一般洗牌,洗4次就可以了。

也就是遍历4次数组就可以了。
Dream_Lu 2005-12-01
  • 打赏
  • 举报
回复
同意tiaoci(我挑刺,我快乐)的算法,基本上算法的增長率是線性的了.而且用內存少,只用了一個數年組.
liangpz_2000 2005-12-01
  • 打赏
  • 举报
回复
johnsuna(缘来是e)和lloach(lloach)提供的方法不是随机分布,做一下统计就知道
int[,] arrIntStatic=null;

private void Static(int[] arr)
{
for( int i=0;i<10;i++)
{
arrIntStatic[i,arr[i]-1]++;
}
}
badboy168 2005-12-01
  • 打赏
  • 举报
回复
俺的算法同5楼的一样,不是看来时间复杂度很大,学习johnsuna(缘来是e)的思想,自己再写个看看
大可山人 2005-11-30
  • 打赏
  • 举报
回复
速度瓶颈:
Random rad=new Random();
rad.Next(0,k+1);
有没有一个办法可以一次性保存rad的所有值,然后,每次直接调用它即可?
cjnet 2005-11-30
  • 打赏
  • 举报
回复
强,顶
大可山人 2005-11-30
  • 打赏
  • 举报
回复
总结一下:

private void button2_Click(object sender, System.EventArgs e)
{
arrInt = InitArray(1,100000);
arrInt = RandomSort(arrInt);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for( int i = 0; i < arrInt.Length-1; i++ )
{
sb.Append(arrInt[i].ToString() + "\r\n");
}
textBox1.Text = sb.ToString();
sb = null;
}

public int[] RandomSort(int[] arr)
{
int k = arr.Length-1; // 要保存的位置
Random rad=new Random();
for( int i = 0; i < arr.Length-1; i++ ) // 执行N-1次循环,随机产生要被打乱的数据所在的位置
{
int idx = rad.Next(0,k+1);
// 交换数据
int n = arr[idx];
arr[idx] = arr[k-1];
arr[k-1] = n;
// 递减要保存的位置
k--;
}
return arr;
}

int[] arrInt = null;
private int[] InitArray(int min, int max)
{
arrInt = new int[max - min];
for(int i = min; i < max; i++)
{
arrInt[i-min] = i;
}
return arrInt;
}
我用了一百万,速度也很快。
止戈而立 2005-11-30
  • 打赏
  • 举报
回复
也还快。。
int []st1=new int[200];
for(int i=0;i<200;i++)
{
st1[i]=i+1;
}
ArrayList al1=new ArrayList(st1);
ArrayList al2=new ArrayList();
Random rad=new Random();
int n=rad.Next(0,200);
for(int j=0;j<200;j++)
{
al2.Add(al1[n]);
this.richTextBox1.Text+=al1[n].ToString()+" ";
al1.Remove(al1[n]);
n=rad.Next(0,199-j);
}
tiaoci 2005-11-30
  • 打赏
  • 举报
回复
哦,我看错了,johnsuna的方法没有问题,

看成仅做随机交换了,不好意思 :)
tiaoci 2005-11-30
  • 打赏
  • 举报
回复
johnsuna(缘来是e) 的方法也不错,

但是有个比较搞得问题就是到底要循环几次才足够随机?

这个是很难确定的,如果光循环 N次,

有很大的概率是其中有个数没有被交换过
止戈而立 2005-11-30
  • 打赏
  • 举报
回复
刚刚想到跟楼上相似的办法。。
用数组下标来控制。。
tiaoci 2005-11-30
  • 打赏
  • 举报
回复
这个算法就足够随机足够好足够快,

谁不服可以挑战 :)

using System;
public class Test
{
public static int [] Random(int n)
{
int [] a = new int[n];
for(int i = 0; i < n; i++) a[i] = i;
Random r = new Random();
for(int i = 0; i < n; i++)
{
int m = a[i];
int k = i + r.Next() % (n - i);
a[i] = a[k];
a[k] = m;
}
return a;
}
public static void Main(string[] args)
{
foreach(int n in Random(20)) Console.WriteLine(n);
}
}
加载更多回复(14)

111,092

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧