【问题标题】:How to shuffle list except an element?如何打乱除元素之外的列表?
【发布时间】:2015-06-28 09:36:35
【问题描述】:

我有一个带有值元素的列表整数:0、7、2、1、6、5。

我知道我可以使用方法

Collections.shuffle(list);

洗牌我的名单。但我不想改变第二个位置的值。它应该始终是 7。

我该怎么做?

【问题讨论】:

    标签: java shuffle


    【解决方案1】:

    您可以将 Collection 洗牌,然后将 7 恢复到第 2 位:

    Collections.shuffle(list);
    list.set(list.indexOf(7),list.get(2));
    list.set(2,7);
    

    或更短:

    Collections.shuffle(list);
    Collections.swap(list, 2, list.indexOf(7));
    

    正如其他人建议的那样,您还可以在洗牌之前删除您希望保留其位置的元素,然后将其添加到同一位置。

    ArrayLists 的两种方法都需要相似的时间(在最坏的情况下是线性的),因为在我的回答中 indexOf 需要线性时间,但是在替代解决方案中删除和添加一个元素(特别是如果索引接近列表的开头)对于ArrayList 将花费线性时间,因为必须将删除/添加索引之后的所有元素推送到新索引。

    【讨论】:

    • 如果你不知道元素的值,只是想将它保留在第二个位置,你可以在洗牌之前将其删除,然后将其添加到第二个位置。
    • @NuongReo 第一个 sn-p 不会复制 7 的值。如果 7 在 shuffle 后保留在 2 索引中,则两个集合操作将相同 - list.set(2,7) 并且不会更改任何内容,因为 set 不会向 List 添加值(它只会更改现有值)。
    • 对于文档:这保留了 Collections.shuffle(...) 的分布属性。
    【解决方案2】:

    简单地防止移动任意数量的元素

    • 从列表中删除它们,
    • 随机播放其余元素,
    • 将它们放回原来的位置(从左开始以避免元素向右移动的问题)。

    【讨论】:

      【解决方案3】:

      有一个更长的替代解决方案,但对于长列表可能更快:

      public static <T> void shuffleExcept(final List<T> list, final int position) {
          List<T> view = new AbstractList<T>() {
              @Override
              public T get(int index) {
                  return list.get(index >= position ? index+1 : index);
              }
      
              @Override
              public T set(int index, T element) {
                  return list.set(index >= position ? index+1 : index, element);
              }
      
              @Override
              public int size() {
                  return list.size()-1;
              }
          };
          Collections.shuffle(view);
      }
      

      这里我们创建一个原始列表的“视图”,它是除了我们想要保留的元素之外的整个列表(我们只是移动后续元素的索引)。接下来我们洗牌这个视图。这就是接口的美妙之处:您可以要求现有方法做一些不同的事情,只需传递新的接口实现即可。

      使用示例:

      List<Integer> input = Arrays.asList(0, 7, 2, 1, 6, 5);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      shuffleExcept(input, 1);
      System.out.println(input);
      

      典型输出:

      [6, 7, 5, 2, 1, 0]
      [5, 7, 6, 1, 2, 0]
      [6, 7, 2, 0, 5, 1]
      [6, 7, 2, 0, 5, 1]
      [2, 7, 0, 5, 6, 1]
      [6, 7, 0, 2, 5, 1]
      [5, 7, 2, 0, 1, 6]
      

      【讨论】:

        猜你喜欢
        • 2021-03-29
        • 1970-01-01
        • 2016-10-04
        • 1970-01-01
        • 2013-09-28
        • 2019-11-29
        • 1970-01-01
        • 2020-03-11
        • 2016-06-25
        相关资源
        最近更新 更多