黑马程序员技术交流社区

标题: [已解决]随机不重复问题 [打印本页]

作者: Tesla时光    时间: 2012-9-2 15:15
标题: [已解决]随机不重复问题
本帖最后由 翁发达 于 2012-9-3 13:24 编辑

我想得到52个0到52之间的随机整数,不重复的
请问为什么我下面这个代码实现不了?哪里错了?
有什么更好的办法吗?

import java.util.*;
class Ran
{
public static boolean biJiao(int[] arr,int a)
{
  boolean b = true;
  for (int y=0; y<arr.length;y++ )
  {
   if (arr[y]==a)
   {
    b=false;
    break;
   }
  }
  return b;
}
public static void main(String[] args)
{
  
  int [] arr1 =new int[52];
  Random ran = new Random();
  for (int x=0;x<arr1.length;)
  {
   int a =ran.nextInt(52);
   boolean b =biJiao(arr1,a);
   if (b)
   {
    arr1[x]=a;
    x++;
   }
  }
}
}



作者: 袁艳超    时间: 2012-9-2 16:51
Random的nextInt(int n)方法,返回一个0-n的随机数,不包括n,
那么用nextInt(52)只能产生一个0-51(包括51)的随机数,
理论上你要产生52个这个区间的不重复的随机数是没问题的,那就必须肯定是0-51,卡的死死的,
可是你要把产生的随机数放到一个new Int[52] 数组中就有问题了,当你创建数组是,默认值是52个0;
所以你要把0-51经验证是否重复后,放进数组中,0是放不进去的,所以会产生死循环
你可以nextInt(53)试试,再打印出数组中的结果看看,里面一定不会有0

至于更好的方法嘛,如果你学到集合后,就会知道Set集合的特点就是不允许重复的数据,
用Set存储产生的随机数,就不用验证是否重复啦,只要Set的size是52了,break就行了

代码如下:
import java.util.*;
import java.util.*;

//1.产生52个0-52之间的随机数,不能重复!
public class RandomNumber{

        public static void main(String[] args) {
                Set<Integer> set = new HashSet<Integer>();
                while (true) {
                        if (set.size() == 52) {
                                break;
                        }
                        int num = new Random().nextInt(52);

                        set.add(num);

                }

                Iterator<Integer> it = set.iterator();
                while (it.hasNext()) {
                        System.out.print(it.next() + "  ");
                }
        }
}
作者: 杨卫腾    时间: 2012-9-2 17:49
楼上的方法可行,运用集合的方法就是挺叼!  可以大大提高效率,可以简化代码!
  1. class RandomTest
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Set<Integer> set = new HashSet<Integer>();
  6.                 Random ran = new Random();
  7.                 while(set.size()<52)
  8.                 {
  9.                         int num = ran.nextInt(52);
  10.                         set.add(num);
  11.                 }
  12.                
  13.                 for(Iterator<Integer> it = set.iterator(); it.hasNext(); )
  14.                 {
  15.                         System.out.print(it.next()+",");
  16.                 }
  17.                 //打印集合
  18.                 System.out.println(set);
  19.         }
  20. }
复制代码

作者: Tesla时光    时间: 2012-9-2 18:08
袁艳超 发表于 2012-9-2 16:51
Random的nextInt(int n)方法,返回一个0-n的随机数,不包括n,
那么用nextInt(52)只能产生一个0-51(包括51)的 ...

我改成int a =ran.nextInt(53);不行,改成int a =ran.nextInt(52)+1;还不行,我就是想知道,我那代码错在哪里?为什么会卡死?我目的是想得到0~51之前不重复的数,也就是每个数都要有
作者: AngieFans85    时间: 2012-9-2 19:55
  1. import java.util.Arrays;
  2. import java.util.Random;

  3. public class Ran {

  4.         public static boolean biJiao(int[] arr, int a) {
  5.                 boolean b = true;
  6.                 for (int y = 0; y < arr.length; y++) {
  7.                         if (arr[y] == a) {
  8.                                 b = false;
  9.                                 break;
  10.                         }
  11.                 }
  12.                 return b;
  13.         }

  14.         public static void main(String[] args) {
  15.                 // int型数组初始化后,每个元素的值都是0.
  16.                 int[] arr1 = new int[52];

  17.                 // 你要想把0放进数组中去,又想将0-51每个数都放进数组中,你就要先将数组中的所有的值都不要
  18.                 // 设置成为0-51的值,这样才可以.我设置成66,你可以随便设置一个不是0-51的数就是了.
  19.                 Arrays.fill(arr1, 66);

  20.                 // 这些代码我就不注释了,就是用你写好的代码.
  21.                 Random ran = new Random();
  22.                 for (int x = 0; x < arr1.length;) {
  23.                         int a = ran.nextInt(52);
  24.                         boolean b = biJiao(arr1, a);
  25.                         if (b) {
  26.                                 arr1[x] = a;
  27.                                 x++;
  28.                         }
  29.                 }

  30.                 // 用Arrays类打印数组要比自己遍历数组方便一些
  31.                 System.out.println(Arrays.toString(arr1));
  32.         }

  33. }
复制代码

作者: 寇龙飞    时间: 2012-9-3 08:29
本帖最后由 寇龙飞 于 2012-9-3 11:09 编辑

两个问题:(首先,得确认,暂定为52个0(包括)到52(不包括)之间的随机数)

1、你的判断包含函数有问题,如果包含,没有返回false。附送我的判断函数contains
受楼下提醒,我检查代码发现楼主写的biJiao函数确实没错,如果包含可以返回fale。
  1. public static boolean contains(int[] arr, int a) {
  2.                 for (int y = 0; y < arr.length; y++) {
  3.                         if (arr[y] == a)
  4.                                 return false;
  5.                 }
  6.                 return true;
  7.         }

  8.         public static boolean biJiao(int[] arr, int a) {
  9.                 boolean b = true;
  10.                 for (int y = 0; y < arr.length; y++) {
  11.                         if (arr[y] == a) {
  12.                                 b = false;
  13.                                 break;
  14.                         }
  15.                 }
  16.                 return b;
  17.         }
复制代码
2、0的问题。那就只有0的处理的问题
  1. int[] arr1 = new int[52];
复制代码
数组元素默认初始化为0,而生成的随机数有需要的0,要判断数组中是否包含是个问题,我数组元素初始化为-1;
  1. int[] arr1 = new int[52];

  2.                 /* 元素初始化为-1 */
  3.                 init(arr1);
复制代码
  1. public static void init(int[] arr) {
  2.                 for (int i = 0; i < arr.length; i++) {
  3.                         arr[i] = -1;
  4.                 }
  5.         }
复制代码
再贴一个我的完整代码与打印结果,先贴结果(后补的):
  1. 数组元素默认值:
  2. 0
  3. 0
  4. (五十个0,不全贴了贴了。)

  5. 52个0(包括)到52(不包括)之间的随机整数
  6. 49
  7. 26
  8. 45
  9. 3
  10. 27
  11. 39
  12. 8
  13. 18
  14. 46
  15. 0
  16. 11
  17. 7
  18. 36
  19. 50
  20. 15
  21. 6
  22. 35
  23. 4
  24. 5
  25. 24
  26. 47
  27. 40
  28. 43
  29. 2
  30. 38
  31. 33
  32. 42
  33. 44
  34. 19
  35. 20
  36. 51
  37. 32
  38. 9
  39. 48
  40. 16
  41. 37
  42. 23
  43. 25
  44. 21
  45. 14
  46. 41
  47. 12
  48. 30
  49. 22
  50. 29
  51. 31
  52. 28
  53. 17
  54. 13
  55. 34
  56. 10
  57. 1
复制代码
再贴完整代码:
  1. package com.itheima.test;

  2. import java.util.Random;

  3. public class Ran {

  4.         public static void init(int[] arr) {
  5.                 for (int i = 0; i < arr.length; i++) {
  6.                         arr[i] = -1;
  7.                 }
  8.         }

  9.         public static boolean contains(int[] arr, int a) {
  10.                 for (int y = 0; y < arr.length; y++) {
  11.                         if (arr[y] == a)
  12.                                 return false;
  13.                 }
  14.                 return true;
  15.         }

  16.         public static void println(int[] arr) {
  17.                 for (int i = 0; i < arr.length; i++) {
  18.                         System.out.println(arr[i]);
  19.                 }
  20.         }

  21.         public static void println(String str) {
  22.                 System.out.println(str);
  23.         }

  24.         public static void main(String[] args) {

  25.                 int[] arr = new int[52];
  26.                 /* 测试数组元素默认值 */
  27.                 println("数组元素默认值:");
  28.                 println(arr);

  29.                 /* 元素初始化为-1 */
  30.                 init(arr);

  31.                 /* 以下代码块最好也封装为函数,此处为了楼主比对,暂时保留。 */
  32.                 Random ran = new Random();
  33.                 for (int x = 0; x < arr.length;) {
  34.                         int a = ran.nextInt(52);
  35.                         boolean b = contains(arr, a);
  36.                         if (b) {
  37.                                 arr[x] = a;
  38.                                 x++;
  39.                         }
  40.                 }

  41.                 /* 测试结果(52个0(包括)到52(不包括)之间的随机整数): */
  42.                 println("52个0(包括)到52(不包括)之间的随机整数");
  43.                 println(arr);

  44.         }
  45. }
复制代码

作者: AngieFans85    时间: 2012-9-3 08:37
寇龙飞 发表于 2012-9-3 08:29
两个问题:(首先,得确认,暂定为52个0(包括)到52(不包括)之间的随机数)

1、你的判断包含函数有问题 ...

1、你的判断包含函数有问题,如果包含,没有返回false。附送我的判断函数contains

其实他的判断包含函数一定问题也没有,他也是包含返回false,不包含返回true.
作者: 寇龙飞    时间: 2012-9-3 10:02
马镱洵 发表于 2012-9-3 08:37
1、你的判断包含函数有问题,如果包含,没有返回false。附送我的判断函数contains

其实他的判断包含函数 ...

他写的是:
  1. b = false;
  2.                                 break;
复制代码
不是
  1. b = false;
  2.                                 return b;
复制代码
他写的对吗?愿闻其详?
作者: AngieFans85    时间: 2012-9-3 10:06
寇龙飞 发表于 2012-9-3 10:02
他写的是:不是他写的对吗?愿闻其详?

当然对:
  1. public static boolean biJiao(int[] arr, int a) {
  2.                 boolean b = true;
  3.                 for (int y = 0; y < arr.length; y++) {
  4.                         if (arr[y] == a) {
  5.                                 b = false;
  6.                                 break;
  7.                         }
  8.                 }
  9.                 return b;
  10.         }
复制代码
如果在数组中找到重复的元素,在break前先将b设置为false,然后跳出整个循环,最后返回false.这很合逻辑啊,找到重复的,返回false啊,他没有错啊.没有找到,b的值就恒为true,你不要忘了,他一开始就将b设置为true的.
作者: AngieFans85    时间: 2012-9-3 10:09
寇龙飞 发表于 2012-9-3 10:02
他写的是:不是他写的对吗?愿闻其详?

他只不过是在方法中用了一个boolean型变量来作记录用,而你是不定义变量,直接就return值.两者在逻辑上没有任何区别,都一样的效果,但是你的代码不用在栈内存中开辟一个boolean型变量所要占的空间,而他的代码需要在栈内存中开辟一个boolean型变量所要占的空间,所以你的代码要更优化一点.
作者: AngieFans85    时间: 2012-9-3 10:28
寇龙飞 发表于 2012-9-3 10:02
他写的是:不是他写的对吗?愿闻其详?

我想回答你,在实际代码中,很多都这样写.从阅读性的角度来看,他的代码的阅读性一点也不差,和你的代码没有区别.
阅读性只和注释和代码的排版有关,跟其他的没有关系.
作者: 寇龙飞    时间: 2012-9-3 10:30
马镱洵 发表于 2012-9-3 10:28
我想回答你,在实际代码中,很多都这样写.从阅读性的角度来看,他的代码的阅读性一点也不差,和你的代码没有 ...

有道理。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2