假如我想从1-40这40个自然数中随机生成10个不重复的自然数,选哪种算法好? 
我想到了以下几种,大家帮我想想 
一   方法选择: 
a.选择方法:采用Random类下的nextInt(40)+1 
b.选择(int)(Math.random()*40)+1 
这两个选哪个好? 二     淘汰重复数(假设选第2个) 
a.
Java code
public class Test
{ public static void main(String[] args)
{
int[] arr = new int[10]; for (int i = 0; i < 10; i++)
{
arr[i] = (int) (Math.random() * 40) + 1;
for (int j = 0; j < i; j++)
{
if (arr[j] == arr[i])
{
i--;
break;
}
}
}
for (int i = 0; i < 10; i++)
System.out.print(arr[i] + " ");
}
}
[/code] 
b.
Java code
import java.util.*;
public class Test
{
    
    public static void main(String[] args)
    {
        int n=40;
        int[] num = new int[n];
        for(int i=0;i<num.length;i++)
            num[i] = i+1;
        int[] arr = new int[10];
        for(int i=0;i<arr.length;i++)
        {
            int r =(int)(Math.random()*n);
            arr[i]=num[r];
            num[r]=num[n-1];
            n--;
        }
        for(int i=0;i<arr.length;i++)
            System.out.print(arr[i]+" ");
    }
}
[/code]
c.
Java code
import java.util.*;
public class Test
{
    
    public static void main(String[] args)
    {
        LinkedList<Integer> myList= new LinkedList<Integer>();
        int n=40;
        for(int i=0;i<n;i++)
            myList.add(i+1);
        int[] arr = new int[10];
        for(int i=0;i<arr.length;i++)
        {
            arr[i]=myList.remove((int)(Math.random()*n));
            n--;
        }
        for(int i=0;i<arr.length;i++)
        {
            System.out.print(arr[i]+" ");
        }
    }
}
[/code]
d.
Java code
import java.util.*;
public class Test
{
    
    public static void main(String[] args)
    {
        Set<Integer> mySet = new LinkedHashSet<Integer>();
        while(mySet.size()<10)
        {
            mySet.add((int)(Math.random()*40+1));
        }
        for(Integer i:mySet)
        {
            System.out.print(i+" ");
        }
    }
}[/code] 
我就想到这几种,不知道哪个性能或者说效率好一些(数据结构不行啊不会分析) 
求高手,若有优化处理请指点

解决方案 »

  1.   

    重发
    a. public class Test
    { public static void main(String[] args)
    {
    int[] arr = new int[10]; for (int i = 0; i < 10; i++)
    {
    arr[i] = (int) (Math.random() * 40) + 1;
    for (int j = 0; j < i; j++)
    {
    if (arr[j] == arr[i])
    {
    i--;
    break;
    }
    }
    }
    for (int i = 0; i < 10; i++)
    System.out.print(arr[i] + " ");
    }
    }
       
    b. 
    import   java.util.*; 
    public   class   Test 

            
            public   static   void   main(String[]   args) 
            { 
                    int   n=40; 
                    int[]   num   =   new   int[n]; 
                    for(int   i=0;i <num.length;i++) 
                            num[i]   =   i+1; 
                    int[]   arr   =   new   int[10]; 
                    for(int   i=0;i <arr.length;i++) 
                    { 
                            int   r   =(int)(Math.random()*n); 
                            arr[i]=num[r]; 
                            num[r]=num[n-1]; 
                            n--; 
                    } 
                    for(int   i=0;i <arr.length;i++) 
                            System.out.print(arr[i]+"   "); 
            } 

     
    c. 
    import   java.util.*; 
    public   class   Test 

            
            public   static   void   main(String[]   args) 
            { 
                    LinkedList <Integer>   myList=   new   LinkedList <Integer> (); 
                    int   n=40; 
                    for(int   i=0;i <n;i++) 
                            myList.add(i+1); 
                    int[]   arr   =   new   int[10]; 
                    for(int   i=0;i <arr.length;i++) 
                    { 
                            arr[i]=myList.remove((int)(Math.random()*n)); 
                            n--; 
                    } 
                    for(int   i=0;i <arr.length;i++) 
                    { 
                            System.out.print(arr[i]+"   "); 
                    } 
            } 

     
    d. 
    import   java.util.*; 
    public   class   Test 

            
            public   static   void   main(String[]   args) 
            { 
                    Set <Integer>   mySet   =   new   LinkedHashSet <Integer> (); 
                    while(mySet.size() <10) 
                    { 
                            mySet.add((int)(Math.random()*40+1)); 
                    } 
                    for(Integer   i:mySet) 
                    { 
                            System.out.print(i+"   "); 
                    } 
            } 
    }  
      

  2.   

    也来写一个
    public class ShuffleTest {
    public static void main(String[] args) 
                    long lstart = System.currentTimeMillis();
    List  myList=   new  ArrayList (); 
                    for(int i=0;i < 40; i++) 
                       myList.add(new Integer(i));
    Collections.shuffle(myList);
    for(int i = 0; i < 10; i++){
    System.out.println(myList.get(i));
    }
    }
    }
      

  3.   

    随机生成若干个放到Set里面,直到放满10个为止~
      

  4.   

     /* 
     把给定的一个任意数组随机排序的类 
       冰冻木马QQ57629776 Email:[email protected] 2007年12月
    */
    public class ArraryToRand
    {
    int [] toRandArrary; //定义一个数组,为原数组的引用
    ArraryToRand(int arrary[]) //参数会引起原来数组的更新,刚好达到目的
    {
    int temp=0,j;
    toRandArrary=arrary; for(int k=0;k<5;k++) //交换5次目的是使数组变得更加乱,也可删除或更改此句中的数字
    for(int i=0;i<arrary.length;i++) //随机交换数组元素,使数组随机排序;
    {
    j=(int)(Math.random()*toRandArrary.length);
    temp=toRandArrary[i];
    toRandArrary[i]=toRandArrary[j];
    toRandArrary[j]=temp;
    }
    }
    /*
    供程序测试用
    */
        //以下是1-40的有序数,经过以上类下将成为无序数
    public static void main(String [] args)
    {
    int [] a=new int[40]; 
                    //先生成一个有序数,然后用以上类随机排序,就可以得到一个无重复的数组了
    for(int i=0;i<a.length;i++)
    a[i]=i+1;
    ArraryToRand myarrary=new ArraryToRand(a);
    for(int i=0;i<a.length;i++)
    System.out.println(a[i]);
    }
    }
    //你可以直接复制,存为ArraryToRand.java 测试一下是否能满足你的要求。
      

  5.   

    import java.util.Random;class f1 
    {
         public static void main(String[] args) 
         {
             int a = 10,k = 0;
             int[] b = new int[a];
             int[] c = new int[a];
             Random r = new Random();
             for(int i = 1;i <= a;i++)
              b[i-1] = i;
             for(int i = 0;i <= 9;i++)
             {
              k = r.nextInt(a);
              System.out.print(" " + b[k]);
              c[i] = b[k];
              b[k] = b[a-1];
              a--;
             }
             System.out.println();
             for(int i = 0;i <= 9;i++)
             {  
              System.out.println(c[i]);
             }
           }
    }
      

  6.   

    个人感觉抽牌算法更合适一些就是说从1~40这四十张牌中随机抽取一张,放到一边
    然后再从剩下的1~39张牌中随机抽取一张,放到一边
    ……
    直至抽取到十张牌为止。
    代码懒得写了大致的伪代码如下:int[40] array{1...40}
    int[10] resultArray{0}
    for i = 0 to 9
    r = random(40-i)
    swap(array[40 - i],array[r]) //交换位置,即模拟取牌中的放到一边的这个动作
    put resultArray[i] = r;循环10次后 resultArray即为10个不重复的随机数了
      

  7.   

    随机生成若干个放到Set里面,直到放满10个为止~
    4楼的这个很经典........
    也就是你的第四种,应该是效率最快的
    你的其余的方法都是由第一种演变而来
    采用第四种
      

  8.   

    四楼这种算法是有致命问题的40个里面挑10个不重复的还看不出来,如果是比如1000个里面挑500个不重复的,用set的方法去取,循环次数会远远大于500次,并且随着总数量的增加,需要进行循环的次数也会急剧增加。
      

  9.   

    通用抽牌算写好了,还挺麻烦 - -
    /*
     * @author talent_marquis<甜菜侯爵>
     * Email: [email protected]
     * Copyright (C) 2007 talent_marquis<甜菜侯爵>
     * All rights reserved.
     */
    package util;
    public class RandomUtil
    { /**
     * @param args
     */
    public static void main( String[] args )
    {
    int[] test = getRandomIntWithoutReduplicate( 0, 40, 10 );
    for( int i : test )
    {
    System.out.println( i );
    }
    } /**
     * get a integer array filled with random integer without reduplicate [min, max)
     * @param min the minimum value
     * @param max the maximum value
     * @param size the capacity of the array
     * @return a integer array filled with random integer without redupulicate
     */
    public static int[] getRandomIntWithoutReduplicate( int min, int max, int size )
    {
    int[] result = new int[size];

    int arraySize = max - min;
    int[] intArray = new int[arraySize];
    // init intArray
    for( int i = 0 ; i < intArray.length ; i++ )
    {
    intArray[i] = i + min;
    }
    // get randome interger without reduplicate
    for( int i = 0 ; i < size ; i++ )
    {
    int c = getRandomInt( min, max - i );
    int index = c - min;
    swap( intArray, index, arraySize - 1 - i );
    result[i] = intArray[ arraySize - 1 - i ];
    }

    return result;
    }

    private static void swap( int[] array, int x, int y )
    {
    int temp = array[x];
    array[x] = array[y];
    array[y] = temp;
    }

    /**
     * get a random Integer with the range [min, max)
     * @param min the minimum value
     * @param max the maximum value
     * @return the random Integer value
     */
    public static int getRandomInt( int min, int max )
    {
    // include min, exclude max
    int result = min + new Double( Math.random() * ( max - min ) ).intValue(); return result;
    }
    }
      

  10.   

    13l
    40-i  i=0-39 
    这样取有重复
      

  11.   

    13l的算法 j=40-i  (j为随机数)   i=0-39  
    是这种取法,有重复
      

  12.   

    没有重复 - -我怕边界条件有问题,还特意测试过从[0,10)随机取9个不重复的值如果有重复的话,是接近100%会出现重复的请仔细看这两行:
    swap( intArray, index, arraySize - 1 - i );
    result[i] = intArray[ arraySize - 1 - i ];我并不是直接把获取到的随机值,经过打乱顺序后取值的,
    而是把它作为一个有序数组的序号来使用
    这个算法应该没问题
      

  13.   

    4楼的 随机生成若干个放到Set里面,直到放满10个为止~ 经典。
    学习下。