【问题标题】:Shuffle sorted subarrays随机排序子数组
【发布时间】:2011-12-21 15:06:18
【问题描述】:

假设我有一个具有一个重要标准的对象,也许还有一些其他数据。

class MyObject {
    int criteria;
    String otherData;
}

我想“随机排序”一个列表,使得给定数据 x,y 使得 x 是标准,y 是 otherData,所有相似的 x 都被分组(和排序)但在子组内,它是洗牌

我的目标是连续运行,可能会给出以下结果

/ 1s first\|/ 2s next \|/ then 3s \
-----------------------------------
1,a 1,b 1,c 2,d 2,e 2,f 3,g 3,h 3,i // other data is in
1,a 1,c 1,b 2,e 2,d 2,f 3,i 3,h 3,g // a random order
1,c 1,a 1,b 2,d 2,f 2,e 3,h 3,i 3,g // within the subgroup
1,b 1,c 1,c 2,e 2,d 2,f 3,g 3,h 3,i 

我目前的计划是创建一个仅比较第一个标准的 Comparable。然后我的“随机排序”可以简单地

list.shuffle(); // get a random ordering
list.sort(); // now group by criteria, leaving the others in a still random state

我的问题是,这是最有效的方法吗?它会真正实现我的目标吗?有没有可能从中出现一些模式?如果有,是什么?

【问题讨论】:

    标签: java algorithm sorting collections shuffle


    【解决方案1】:

    我在您的方法中看到的唯一优化是使用某种洗牌迭代器,而不是实际洗牌数据。但这不会改变算法的复杂性,因为洗牌成本在最坏的情况下是线性的,而排序最多是 n log(n)

    【讨论】:

      【解决方案2】:

      我相信这会起作用并且是渐近最优的。如果确保使用稳定的排序,最容易分析,但我认为分组阶段无论如何都不会引入偏差。

      如果您想编写更清楚地表达您的意图的代码,您可以将值插入TreeMap<Integer, List<MyObject>>,将给定整数的所有值分组到同一个列表中。然后按键顺序(从最低到最高)迭代映射的内容,打乱每个子列表,然后将其内容转储到最终输出列表中。在我看来,这种方法更“明显正确”,但我相信你的方法也同样有效。

      【讨论】:

      • 比较器不知道未排序的字段。因此,我很确定不稳定的排序不会在这里引入偏差。
      • 是的,我同意。我的意思是,如果你想提出一个正式的论点,你需要说(a)排序已经置换而不考虑其他字段,并且(b)一致置换无偏随机洗牌的顺序是也是一个无偏的随机洗牌。这两个事实似乎很明显,但它们确实使论点更加微妙。
      【解决方案3】:

      想想你想要做什么,在你考虑实现之前,并尝试从现有的 JDK 类中找到合适的。

      我会使用Map<Integer, List<MyObject>> 来立即解决分组问题,然后我可以Collections.shuffle() 列表,如果我真的想要一个列表,我可以转储列表将地图值合并到一个列表中:

      Map<Integer, List<MyObject>> map = new HashMap<Integer, List<MyObject>>();
      ...
      List oneList = new ArrayList<MyObject>(map.values());
      for (List<?> list : map.values())
          oneList.addAll(list);
      

      【讨论】:

      • 我曾考虑过这一点,但这是应用程序中时间最关键的循环。它必须在每次迭代时重新排序优先级,这样做我每次都必须重新创建整个地图/列表结构。我还看到我必须对oneList 进行排序,以确保它们都按正确的顺序排列,看看values() 没有分配给它的顺序。
      • 我还要注意,列表的长度不能超过 10,这进一步增加了这种开销的幅度。
      • 您可以使用有序映射来维护int criteria 的顺序。另外,我建议您保留地图,并且仅在绝对需要时才呈现到列表中 - 或者更改您的应用程序以使用地图。顺便说一句,它应该是criterion,而不是criteria:criteria 是criterion 的复数,你只有一个int,除非它是位掩码:)跨度>
      • int 表示所有条件的集合,恰好包含一个元素。 :-) 不幸的是,任何人都必须在每次迭代时将其呈现为列表。它需要可供决策算法正确地做出决策。如果我没有让他们做出决定的列表,即使在同一次迭代中,他们也可能会得到不同的结果,这是他们不应该的。
      猜你喜欢
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      相关资源
      最近更新 更多