Algorithm 将N个列表中的项目合并为一个均衡分布的项目的好算法?
假设我有以下三个列表 A1Algorithm 将N个列表中的项目合并为一个均衡分布的项目的好算法?,algorithm,list,Algorithm,List,假设我有以下三个列表 A1 A2 A3 B1 B2 C1 C2 C3 C4 碳五 我想将它们合并成一个列表,每个列表中的项目尽可能均匀分布,如下图所示: C1 A1 C2 B1 C3 A2 C4 B2 A3 碳五 我使用的是.NET3.5/C,但我更关注的是如何使用特定代码 编辑:我需要保持原始列表中元素的顺序。您可以简单地将三个列表合并为一个列表,然后取消对该列表的排序。一份未排序的列表应该可以实现您的“均匀分布”要求,而无需付出太多努力 这是unsort的一个实现:。我正在考虑一种分而治之的
A2
A3 B1
B2 C1
C2
C3
C4
碳五 我想将它们合并成一个列表,每个列表中的项目尽可能均匀分布,如下图所示: C1
A1
C2
B1
C3
A2
C4
B2
A3
碳五 我使用的是.NET3.5/C,但我更关注的是如何使用特定代码
编辑:我需要保持原始列表中元素的顺序。您可以简单地将三个列表合并为一个列表,然后取消对该列表的排序。一份未排序的列表应该可以实现您的“均匀分布”要求,而无需付出太多努力
这是unsort的一个实现:。我正在考虑一种分而治之的方法。您将所有元素大于1的列表拆分为两半并递归的每次迭代。当你到达一个点,所有的列表除了一个是一个元素,你可以随机组合他们,弹出一个级别,并随机组合列表删除从该帧的长度是一。。。等等 我是这样想的:
- filter lists into three categories
- lists of length 1
- first half of the elements of lists with > 1 elements
- second half of the elements of lists with > 1 elements
- recurse on the first and second half of the lists if they have > 1 element
- combine results of above computation in order
- randomly combine the list of singletons into returned list
python伪代码中的一个快速建议:
merge = list()
lists = list(list_a, list_b, list_c)
lists.sort_by(length, descending)
while lists is not empty:
l = lists.remove_first()
merge.append(l.remove_first())
if l is not empty:
next = lists.remove_first()
lists.append(l)
lists.sort_by(length, descending)
lists.prepend(next)
这将比此处的其他建议更均匀地分布较短列表中的元素
编辑:这也有O(n)的优点,这总是好的:)首先,这个答案更像是一个思路,而不是一个复杂的解决方案 好的,你有一个3个项目的列表(A1,A2,A3),你希望A1在目标列表的前1/3,A2在目标列表的第二个1/3,A3在第三个1/3。同样,您希望B1位于前1/2,以此类推 因此,您将10个列表分配为一个数组,然后从项目最多的列表开始,在本例中为C。计算C1应落下的位置(1.5)将C1落在最近的位置(在本例中为1或2),然后计算C2应落下的位置(3.5),并继续此过程,直到没有更多的C 然后按照第二至最多项目的列表进行操作。在本例中,A.计算A1的位置(1.66),因此首先尝试2。如果已经将C1放在那里,请尝试1。对A2(4.66)和A3(7.66)执行相同的操作。最后,我们确实列出了B。B1应该是2.5,所以试试2或3。如果两者都被取下,尝试1和4,并保持径向向外移动,直到找到一个空白点。对B2做同样的操作 如果您选择较低的数字,您将得到如下结果: C1 A1 C2 A2 C3 B1 C4 A3 C5 B2 或者,如果选择较高的数字: A1 C1 B1 C2 A2 C3 A3 C4 B2 C5 这似乎对您的示例列表非常有效,但我不知道它在多大程度上可以扩展到包含多个项目的多个列表。试试看,告诉我进展如何。
- 制作列表的哈希表
- 对于每个列表,将列表中的第n个元素存储在键
(/n(+(长度列表)1))
- (可选)洗牌哈希表中每个键下的列表,或以某种方式对它们进行排序
- 按排序键连接散列中的列表
公共列表equimix(列表输入){
//将最大列表排序为最小列表
Collections.sort(输入,新的Comparator(){
公共整数比较(列表a1、列表a2){
返回a2.size()-a1.size();
}
});
列表输出=输入。获取(0);
对于(int i=1;ilistA.size()){
列表温度;
temp=listB;
listB=listA;
listA=温度;
}
列表输出=listA;
double-shiftceff=(double)listA.size()/listB.size();
双浮点计数器=移位效率;
用于(字符串项:listB){
int insertionIndex=(int)Math.round(floatCounter);
输出.添加(插入索引,项);
浮动计数器+=(1+shiftcoff);
}
返回输出;
}
听起来像是将元素随机化。虽然它可能在大多数情况下都会起作用,但有时你会得到一个相当不平衡的分布。是的,我在发布我的解决方案后注意到了。这会比Will的答案更好吗?在我看来,你不只是想将它们结合起来,你希望它们像拉链一样均匀地融合在一起,或者像汽车在高速公路上礼貌地融合在一起。我说的对吗?这个算法有一个众所周知的名字吗?在这一点上的一个变体是使用Bresenham的直线算法,而不是步骤4中的浮点计数器。将N个对象均匀地插入到现有的M个对象列表中,相当于从到枚举光栅化线的点。。。溢出/舍入是bresenhams的核心。@AndrewRollings你能详细解释一下吗,或者一个伪代码
对我来说就足够理解了?我无法清楚地理解您的答案。此伪代码并非在所有情况下都有效。我实现了它,并尝试使用大小为2和6的两个列表。试图从空列表中删除元素时出现索引器错误。