2014-12-07 57 views
0

我有一个int向量,如int[] A = {6, 1, 5, 3, 4, 2},我需要在三个步骤中随机选取两个不同的元素,并且每个步骤应该从其他步骤中挑选不同的元素。每次在迭代中从int数组中挑选不同的随机元素?

例如:

  1. 选择2,5
  2. 选择6,3
  3. 选择4,1

我尝试这样做,但我失败了很多次。我会很感激任何帮助。 这是我最后的代码。

public class T8 { 
    public static void main(String[] args) { 
     int n=5, d=2, r, i, j; 
     int[] B = new int [d]; 
     Random rand=new Random(); 
     System.out.println("d = "+d); 
     Integer[] A = {10,12,3,4,5}; 
     List<Integer> list = new ArrayList<Integer>(Arrays.asList(A)); 
     for(j=0; j<d; j++){ 
      r = rand.nextInt(n); 
      B[j] = A[r]; 
      System.out.print(B[j]+" "); 
      list.remove(r); 
      A = list.toArray(new Integer[0]); 
      n=n-1; 
     } 

     System.out.println(""); 
     for(j=0; j<n; j++){ 
      System.out.print(A[j]+" "); 
     } 
    } 
} 
+2

你试过了什么代码? – markspace 2014-12-07 00:24:27

+0

一种可能的方法是:将选中的每个元素捕获到该选项的变量中,然后将其在原始数组中的索引设置为无效值,然后知道您已经选择了什么。然后把所有的元素都放回去。 – abiessu 2014-12-07 00:31:05

+0

非常感谢,我已经通过加入我自己的代码编辑了帖子。 – John 2014-12-07 00:34:10

回答

0

不是最佳的办法:您可以使用random.nextInt和每次当您生成随机数检查是否是独一无二的,如果不产生新的随机指数。例如。

import java.util.HashSet; 
import java.util.Random; 
import java.util.Set; 

public class RandomPicker { 

    public static void main(String[] args) { 

     int[] arr = {6, 1, 5, 3, 4, 2}; 
     Random random = new Random(); 
     Set<Integer> randoms = new HashSet<>(); 
     while (arr.length != randoms.size()) { 
      int i = nextRandomIndex(arr, random, randoms); 
      int j = nextRandomIndex(arr, random, randoms); 
      System.out.printf("%d,%d\n", arr[i], arr[j]); 
     } 
    } 

    private static int nextRandomIndex(int[] arr, Random random, Set<Integer> randoms) { 
     int i = random.nextInt(arr.length); 
     while (randoms.contains(i)) { 
      i= random.nextInt(arr.length); 
     } 
     randoms.add(i); 
     return i; 
    } 
} 

可能的输出

4,1 
6,3 
5,2 

更好的办法是重新洗牌数组,然后遍历它(如果你不想修改数组,然后通过原始数组洗牌方法的副本)。例如。

import java.util.Arrays; 
import java.util.Random; 

public class RandomPicker { 

    public static void main(String[] args) { 

     int[] arr = {6, 1, 5, 3, 4, 2}; 
     int[] copy = Arrays.copyOf(arr, arr.length); 
     shuffle(copy); 
     int index = 0; 
     for (int i = 0; i < arr.length/2; i++) { 
      System.out.printf("%d, %d\n",copy[index], copy[++index]); 
     } 
    } 

    private static void shuffle(int[] arr) 
    { 
     int index; 
     int temp; 
     Random rand = new Random(); 
     int i = arr.length - 1; 
     while (i > 0) 
     { 
      index = rand.nextInt(i + 1); 
      temp = arr[index]; 
      arr[index] = arr[i]; 
      arr[i] = temp; 
      i--; 
     } 
    } 
} 
+0

非常感谢,我现在就试试。 – John 2014-12-07 00:35:04

+0

非常感谢你的工作,再次感谢。 – John 2014-12-08 14:25:26

0

许多方式,你可以这样做:

  1. 复制数组元素成List然后随机从列表中删除元素。

  2. 使用一个(弱)伪随机数发生器,以可预测的方式遍历所有索引。

  3. 创建之前返回的所有元素的HashSet

  4. 使用shuffle方法洗牌就地输入数组,然后只返回在时间中的元素一个,直到你达到length - 1从指数0开始。

  5. 如果不能改变输入阵列,则创建填充值0length - 1阵列,混洗阵列,然后通过使用其值作为索引到所述第一阵列,其阵列步骤。

@ sol4me的解决方案(它是上述3.和5.的混合)具有一个有趣的属性。计算行为是概率:

  • 当你到达的顺序,找到并返回尚未使用的索引之前的增长“令人担忧”所花费的时间结束。

  • 理论上的最坏情况行为是nextRandomIndex永不终止。 (只有当你的随机数发生器有偏差时,才会发生这种情况。)

  • 对于“完美”的随机数发生器,由nextRandomIndex执行的迭代次数是有限的,但我们不能在它上面放置一个上限。

  • 对于伪随机数发生器,发生器的周期长度是迭代次数的上限。


你尝试的解决方案是接近第一个我建议。但有一个问题是,

List<Integer> list = new ArrayList<Integer>(Arrays.asList(A)); 

是创建一个“视图”到阵列,其长度不能改变。如果您创建一个ArrayList,然后数组元素复制到列表中,则不会在remove中看到例外情况。

另一个问题是这样的:

A = list.toArray(new Integer[0]); 

是非常低效。不需要将列表转换回数组。只需保留下次列表。

+0

非常感谢,您的意见非常有用,非常感谢。 – John 2014-12-08 14:26:12

相关问题