【问题标题】:ArrayList randomize with index change for all elementsArrayList 随机化所有元素的索引更改
【发布时间】:2015-02-01 23:21:16
【问题描述】:

如何随机化 arrayList 所以旧索引不能与所有元素的新索引相同

例如 包含 3 个项目的列表

arrayList 随机化后

旧索引新索引

1<-->2 <--different
2<-->1 <--different
3<-->3 <--same is not allowed

我想确认一下

1<-->3 <--different
2<-->1 <--different
3<-->2 <--different

【问题讨论】:

  • 您确定要随机化吗?我认为有约束可以排除随机性。还是简单地重新排列?如果是这样,您可以简单地重新分配给(index+n) % array.length,其中 n 是任意数字。
  • 有趣的是,一些 OP 在他们只花了 10 分钟发布问题后 30 秒似乎就消失了...... ;)
  • 这只是确保两个数组以相同的方式随机使用相同的种子。即使有两个不同的种子,它也有可能得到相同的值。

标签: java


【解决方案1】:

这是你必须自己实现的东西。

  • 洗牌可能是一系列随机交换(例如交换 1 -> 4, 交换 3 -> 2)。
  • 跟踪每个元素的新位置(例如 4 3 2 1 5 用于具有 5 个元素的列表和上述 shuffle 操作)。
  • 如果任何元素仍在其旧位置(该示例中为 5), 继续洗牌。

听起来很有趣。

【讨论】:

    【解决方案2】:
    Collections.shuffle(List<?> list)
    

    这应该适用于不包含空值的列表:

    static <T> void shuffleList(List<T> list) {
        List<T> temp = new ArrayList<T>(list);
        Random rand = new Random();
    
        for (int i = 0; i < list.size(); i++) {
            int newPos = rand.nextInt(list.size());
            while (newPos == i||temp.get(newPos)==null) {
                newPos = rand.nextInt(list.size());
            }
            list.set(i, temp.get(newPos));
            temp.set(newPos,null);
        }
    }
    

    对于具有空值的列表:

    static <T> void shuffleList(List<T> list) {
        List<T> temp = new ArrayList<T>(list);
        Integer [] indexes=new Integer[list.size()];
        for (int i=0;i<list.size();i++){
            indexes[i]=i;
        }
        Random rand = new Random();
    
        for (int i = 0; i < list.size(); i++) {
            int newPos = rand.nextInt(list.size());
            while (newPos == i||indexes[newPos]==null) {
                newPos = rand.nextInt(list.size());
            }
            list.set(i, temp.get(newPos));
            indexes[newPos]=null;
        }
    }
    

    【讨论】:

    • 我不认为这是正确的,因为它不能保证每个元素最终都在一个新的位置。
    • 不,我错了。它是正确的。不过你的解释有点稀疏。
    • 根据问题是不正确的。 OP 希望所有元素都处于不同的位置。这并不保证这一点。
    • 这个实现从最后一个元素到第二个元素向后遍历列表,重复地将随机选择的元素交换到“当前位置”。元素是从列表中从第一个元素到当前位置(含)的部分随机选择的。 从这里:docs.oracle.com/javase/6/docs/api/java/util/…
    • 好吧,我只运行了大约两次,提供的值 OP 和 2 没有从原来的位置移动。这个答案建议用随机的seeds 做两次:stackoverflow.com/questions/4228975/how-to-randomize-arraylistv
    【解决方案3】:
    var numExist = [];
    while(numExist.length!=array.length){
      var randomizer = new Random();
      int i =0;
      var num = randomizer.nextInt(array.length);
      if(!numExist.contains(num)){
        array[i]=array[num];
        numExist.add(num);
        i++;
      }
    }
    

    【讨论】:

    • 没有任何解释的代码转储很少有帮助。 Stack Overflow 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请edit您的问题并解释它如何比OP提供的更好。
    【解决方案4】:

    以下是 Fisher-Yates 的一种变体,它迎合了至少一个项目将保留在其原始位置的可能性。

    当前的Collections.shuffle() 没有对列表进行完全随机化。

       public static void shuffle(List<Integer> list) {
          Random r = new Random();
          int size = list.size();
          boolean flag = true;
          for (int i = size - 1; i >= 0 && flag; i--) {
             int pos = r.nextInt(i + 1);
             if (list.get(i) == pos) {
                if (i == 0) {
                   flag = false;
                   break;
                }
                // counter the upcoming decrement by incrementing i
                i++;
                continue;
             }
             int temp = list.get(i);
             list.set(i, list.get(pos));
             list.set(pos, temp);
          }
    
    // At this juncture, list.get(0) points to itself so choose a random candidate
    // and swap them.
    
          if (!flag) {
             int pos = r.nextInt(size - 1) + 1;
             int temp = list.get(0);
             list.set(0, list.get(pos));
             list.set(pos, list.get(0));
          }
       }
    
    

    可能仍然存在最终问题,但我使用以下代码来测试 随机播放,未检测到任何问题。

          for (int k = 0; k < 100000; k++) {
             List<Integer> list =
                   IntStream.range(0, 52).boxed().collect(Collectors.toList());
             System.out.println("Test run #" + k);
             // Collections.shuffle(list);
             shuffle(list);
             for (int i = 0; i < list.size(); i++) {
                if (i == list.get(i)) {
                   System.out.printf("Oops! List.get(%d) == %d%n", list.get(i), i);
                }
             }
          }
    
    

    【讨论】:

      猜你喜欢
      • 2014-12-12
      • 1970-01-01
      • 2014-06-27
      • 2020-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多