让我们说我有一个具有一个重要标准的对象,也许还有一些其他数据。
class MyObject {
int criteria;
String otherData;
}
我想" shuffle-sort"一个列表,给定数据x,y使得x是标准,y是其他数据,所有相似的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。然后我的" shuffle-sort"可以简单地
list.shuffle(); // get a random ordering
list.sort(); // now group by criteria, leaving the others in a still random state
我的问题是,这是最有效的方法吗?它真的会实现我的目标吗?是否会出现一些可能出现的模式?如果是这样,是什么?
答案 0 :(得分:2)
我相信这会起作用并且渐近最优。分析是否确保使用稳定排序是最简单的,但我认为分组阶段不会引入偏差。
如果要编写更明显表达意图的代码,可以将值插入TreeMap<Integer, List<MyObject>>
,将给定整数的所有值分组到同一个列表中。然后按键顺序(从最低到最高)迭代映射的内容,对每个子列表进行混洗,然后将其内容转储到最终输出列表中。在我看来,这种方法更“明显正确”,但我相信你的方法同样适用。
答案 1 :(得分:1)
我在你的方法中看到的唯一优化是使用某种改组迭代器而不是实际改组数据。但这不会改变算法的复杂性,因为洗牌成本最差是线性的,排序最多也是n log(n)
答案 2 :(得分:0)
考虑一下你想要做什么,在之前考虑实现,并尝试从现有的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);