数字数组的最优冒泡排序算法
修复正整数n
和k
。
令 A
为长度为 n
的数组,其中 A[i]
为长度为 k
的数组,其中每个条目都是ni
。例如,对于 n=5
和 k=1
,这仅
[ [5] , [4] , [3] , [2] , [1] ]
适用于 n=5
和 k=2
code>,这是
[ [5,5] , [4,4] , [3,3] , [2,2] , [1,1] ]
目标是通过交换相邻数组中的数字来对这个数组进行冒泡排序(例如将 A[i][j1]
与 A[i+1][j2 ]
) 直到每个条目对于每个 i
,A[i]
是 i+1
。
问题是:需要多少次交换以及最佳算法是什么?
注意: 有很多很多更好的排序算法可供使用。然而,对于这个问题,我只对应用如上所述的冒泡排序感兴趣。我只能交换相邻数组中的条目,并且我只对必要的此类交换的最小数量感兴趣。我确实很欣赏对其他排序算法的所有建议,但这就是我想要理解的问题。
示例:
对于 k=1
,这是众所周知的。交换次数为A
视为排列的倒数,因此最小交换次数为二项式系数(n Choose 2) = n(n-1)/2
这可以通过交换任何无序对来实现:A[i] > A[j]
。对于第一个示例,这是一个最佳冒泡排序:
[ [5] , [4] , [3] , [2] , [1] ]
[ [4] , [5] , [3] , [2] , [1] ]
[ [4] , [5] , [2] , [3] , [1] ]
[ [4] , [2] , [5] , [3] , [1] ]
[ [4] , [2] , [5] , [1] , [3] ]
[ [4] , [2] , [1] , [5] , [3] ]
[ [4] , [1] , [2] , [5] , [3] ]
[ [1] , [4] , [2] , [5] , [3] ]
[ [1] , [4] , [2] , [3] , [5] ]
[ [1] , [2] , [4] , [3] , [5] ]
[ [1] , [2] , [3] , [4] , [5] ]
对于 k=2
,使用相同的策略将给出所需的 2(n 选择 2)
交换范围。对于上面的示例,这意味着 20
交换。但有一个仅使用 15
交换的解决方案:
[ [5,5] , [4,4] , [3,3] , [2,2] , [1,1] ]
[ [5,4] , [5,4] , [3,3] , [2,2] , [1,1] ]
[ [5,4] , [3,4] , [5,3] , [2,2] , [1,1] ]
[ [5,4] , [3,4] , [2,3] , [5,2] , [1,1] ]
[ [5,4] , [3,4] , [2,3] , [1,2] , [5,1] ]
[ [5,4] , [3,4] , [2,1] , [3,2] , [5,1] ]
[ [5,4] , [3,1] , [2,4] , [3,2] , [5,1] ]
[ [1,4] , [3,5] , [2,4] , [3,2] , [5,1] ]
[ [1,4] , [3,2] , [5,4] , [3,2] , [5,1] ]
[ [1,4] , [3,2] , [2,4] , [3,5] , [5,1] ]
[ [1,4] , [3,2] , [2,4] , [3,1] , [5,5] ]
[ [1,4] , [3,2] , [2,1] , [3,4] , [5,5] ]
[ [1,4] , [1,2] , [2,3] , [3,4] , [5,5] ]
[ [1,1] , [4,2] , [2,3] , [3,4] , [5,5] ]
[ [1,1] , [2,2] , [4,3] , [3,4] , [5,5] ]
[ [1,1] , [2,2] , [3,3] , [4,4] , [5,5] ]
该解决方案对于 n=5
和 k=2
是最佳的(通过暴力证明找到所有的解决方案)。对于 n=6
,最佳解决方案需要 22
次交换,但该解决方案看起来不如 n=5
的解决方案那么好(遵循 5 右,然后 1 左,然后 5 右,等等),所以我仍然不知道最佳策略,更不用说公式或更好的交换次数限制。
我已经思考这个问题好几天了,但还没有想出任何有启发性的东西。如果有人对此问题有任何想法,请分享。我很高兴能够了解有关 k=2
案例的更多信息。对于一般情况的任何想法就更好了。
编辑:如果我不能按照您的喜好激发这个问题,我很抱歉,但这里有一个尝试:对排列进行排序所需的冒泡排序数量是组合学和数论中非常重要的统计量,称为排列的反转数。您可以使用更好的算法对无序排列进行排序,但这就是给您代数意义的算法。如果这没有帮助,也许这个相关的帖子可能: 什么是泡沫排序有什么好处?
更新:下面最旧的答案给出交换次数的下限(和上限)。 第二个最旧的答案 给出了一个非常接近这个下限(通常达到它)的算法。如果有人可以改进界限,或者更好的是证明下面给出的算法是最优的,那就太棒了。
Fix positive integers n
and k
.
Let A
be an array of length n
with A[i]
an array of length k
where every entry is n-i
. For example, with n=5
and k=1
, this is just
[ [5] , [4] , [3] , [2] , [1] ]
and for n=5
and k=2
, this is
[ [5,5] , [4,4] , [3,3] , [2,2] , [1,1] ]
The goal is to bubble sort this array of arrays by swapping numbers in adjacent arrays (e.g. swap A[i][j1]
with A[i+1][j2]
) until every entry of A[i]
is i+1
for every i
.
The question is: how many swaps are necessary and what's an optimal algorithm?
NOTE: There are many, many better sorting algorithms to use. However, for this question, I am only interested in applying a bubble sort as described above. I can only interchange entries from adjacent arrays, and I am only interested in the minimum number of such interchanges necessary. I do appreciate all the suggestions for other sorting algorithms, but this is the problem that I am trying to understand.
EXAMPLES:
For k=1
, this is well known. The number of swaps is the inversion number of A
regarded as a permutation, and so the minimum number of swaps is the binomial coefficient (n choose 2) = n(n-1)/2
and this can be attained by swapping any out of order pair: A[i] > A[j]
. For the first example, here's an optimal bubble sort:
[ [5] , [4] , [3] , [2] , [1] ]
[ [4] , [5] , [3] , [2] , [1] ]
[ [4] , [5] , [2] , [3] , [1] ]
[ [4] , [2] , [5] , [3] , [1] ]
[ [4] , [2] , [5] , [1] , [3] ]
[ [4] , [2] , [1] , [5] , [3] ]
[ [4] , [1] , [2] , [5] , [3] ]
[ [1] , [4] , [2] , [5] , [3] ]
[ [1] , [4] , [2] , [3] , [5] ]
[ [1] , [2] , [4] , [3] , [5] ]
[ [1] , [2] , [3] , [4] , [5] ]
For k=2
, using the same strategy would give a bound of 2 (n choose 2)
swaps needed. For the example above, that means 20
swaps. But there is a solution that uses only 15
swaps:
[ [5,5] , [4,4] , [3,3] , [2,2] , [1,1] ]
[ [5,4] , [5,4] , [3,3] , [2,2] , [1,1] ]
[ [5,4] , [3,4] , [5,3] , [2,2] , [1,1] ]
[ [5,4] , [3,4] , [2,3] , [5,2] , [1,1] ]
[ [5,4] , [3,4] , [2,3] , [1,2] , [5,1] ]
[ [5,4] , [3,4] , [2,1] , [3,2] , [5,1] ]
[ [5,4] , [3,1] , [2,4] , [3,2] , [5,1] ]
[ [1,4] , [3,5] , [2,4] , [3,2] , [5,1] ]
[ [1,4] , [3,2] , [5,4] , [3,2] , [5,1] ]
[ [1,4] , [3,2] , [2,4] , [3,5] , [5,1] ]
[ [1,4] , [3,2] , [2,4] , [3,1] , [5,5] ]
[ [1,4] , [3,2] , [2,1] , [3,4] , [5,5] ]
[ [1,4] , [1,2] , [2,3] , [3,4] , [5,5] ]
[ [1,1] , [4,2] , [2,3] , [3,4] , [5,5] ]
[ [1,1] , [2,2] , [4,3] , [3,4] , [5,5] ]
[ [1,1] , [2,2] , [3,3] , [4,4] , [5,5] ]
This solution is optimal for n=5
and k=2
(proof by brute force to find all solutions). For n=6
, the best solution takes 22
swaps, but the solution doesn't look as nice as the one for n=5
(follow the 5 right, then the 1 left, then the 5 right, etc), so I still don't know an optimal strategy, much less a formula or better bound for the number of swaps.
I've been thinking about this for a couple of days now and haven't come up with anything enlightening. If anyone has any thoughts on this problem, then please share them. I'd be thrilled with knowing more about the k=2
case. Even better for any thoughts on the general case.
EDIT: I apologize if I cannot motivate this problem to your liking, but here's an attempt: the number of bubble sorts needed to sort a permutation is a very important statistic in combinatorics and number theory, called the inversion number of the permutation. You can sort an out of order permutation using much better algorithms, but this is the one that gives you the algebraic meaning. If that doesn't help, perhaps this related SO post may: What is a bubble sort good for?
UPDATE: The oldest answer below gives a lower (and upper) bound for the number of swaps. The second oldest answer gives an algorithm that comes really close to this lower bound (often attaining it). It would be fantastic if someone could improve the bound, or, even better, prove that the algorithm given below is optimal.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这不是最佳答案,但我想分享我的尝试,因为有人可能会改进它。我没有考虑找到一个公式来计算最小交换次数,而是考虑了最佳算法。该算法基于k=2。
基本思想是基于信息增益。让我们假设 A = {[i,j] : 1<=i<=n, 1<=j<=n} 表示一个配置。在每个步骤中,我们都有 4 * (n-1) 次可能的交换,以从一种配置移动到另一种配置。例如,如果 n = 2(即 A = [ {2,2}, {1,1} ] ),则我们有 4 种可能的交换 A[0][0] <-> A[1][0]、A[0][0]>> A[1][1]、A[0][1]>> A[1][0]和A[0][1]…… A[1][1]。因此,我们的目标是当我们需要从一种配置移动到另一种配置时选择具有高信息增益的交换。
棘手的部分是“如何计算信息增益”。在我的解决方案(如下)中,信息增益基于值与其正确位置的距离。让我向您展示我的代码(用 C++ 编写)以了解我想说的内容:
我针对 n=1,2,... 和 7 的情况运行了上述代码。以下分别是答案(交换次数): 0、2、5、10、15、23(非常接近)和 31。我认为当 n 为偶数时,函数 Gain() 不能很好地工作。您能否通过验证 n = 7 时的交换次数来确认这一点。方程的下限是 31,因此这是 n = 7 时的最佳交换次数。
我在这里打印 n = 5 时的输出(因为您是寻找模式):
This is not an optimal answer, but i would like to share my attempt as someone may improve it. I did not thought about finding a formula to calculate the minimum number of swaps but rather on the optimal algorithm. The algorithm is based on k = 2.
The basic idea is based on information gain. Let us assume that A = {[i,j] : 1<=i<=n, 1<=j<=n} represents a configuration. In each step, we have 4 * (n-1) possible swapping to move from one configuration to another configuration. For example if n = 2 (i.e. A = [ {2,2}, {1,1} ] ), then we have 4 possible swapping A[0][0] <-> A[1][0], A[0][0] <-> A[1][1], A[0][1] <-> A[1][0], and A[0][1] <-> A[1][1]. Thus, our objective is to select the swap that has high information gain when we need to move from one configuration to another configuration.
The tricky part will be "how to calculate the information gain". In my solution (below), the information gain is based on the distance of a value from its correct position. Let me show you my code (written in C++) to understand what i am trying to say:
I ran the above code for cases n=1,2,... and 7. Here are the answers (number of swaps) respectively: 0, 2, 5, 10, 15, 23 (very close), and 31. I think that the function gain() does not work well when n is even. Can you confirm that by validating the number of swaps when n = 7. The lower bound of your equation is 31 so this is the optimal number of swaps when n = 7.
I am printing here the output when n = 5 (since you are looking for a pattern):
我知道回答自己的问题相当俗气,但我刚刚弄清楚这一点,它更接近于答案而不是问题的一部分。然而,这不是一个完整的答案,不会被接受,所以如果有人可以改进这个答案,请发表想法。
k=2
的最小交换次数(例如m
)受以下限制:为什么会这样?
上限对数组的第一个元素进行冒泡排序,然后对数组的第二个元素进行冒泡排序。这部分并不那么棘手。
下限有点棘手,但我是这样得出的。让我们来计算一下通过的次数,当较大的数字从较小的数字的左侧移动到该数字的右侧时,就会发生通过。这可能发生在
a
和b
1 次交换中,其中a
较大并且位于b
左侧的数组中>。如果在一次交换中将a
移动到带有b
的数组,然后在以后的交换中继续移动,则也可能需要 2 次交换。为了正确地记录事情,在这种情况下,将传球数分成两半。为了使计数更容易,当两个相同的数字分开然后重新组合时,也算一次通过。数组在
(2n select 2)
传递后完全排序,因此唯一的问题是一次交换可以发生多少次传递。下面是一个交换a
和c
的简单示例:现在让我们计算可能发生的最大传递次数:
a > c
,我们肯定获得 1 个完整通过。a > b
,那么我们得到 1/2 通过,因为a
一定在某个时刻离开了b
。a > d
,那么我们就得到 1/2 pass,因为a
在某个时刻将位于d
的右侧。c < d
,那么我们得到 1/2 通过,因为d
一定在某个时刻离开了c
。c < b
,然后我们得到 1/2 通过,因为b
在某个时刻将位于c
的右侧。因此,在交换中你能做的最好的事情就是获得 3 次传球(1 次全传球和 4 次半传球)。
为什么这不是一个完整的答案?
我不知道下限是否总是可以达到的!我不这么认为,而且,尽管多次尝试失败,我还是无法编写出实现它的算法。
I know it's rather tacky to answer one's own question, but I've just figured this out and it is closer to an answer than it is to part of the question. However, this is not a complete answer and will not get accepted, so please post thoughts if anyone can improve this.
The minimum number of swaps, say
m
, fork=2
is bounded by:Why does this work?
The upper bound comes doing a bubble sort on the first elements of the arrays, followed by a bubble sort on the second elements of the arrays. That part isn't so tricky.
The lower bound is a bit tricky, but here's how I came to it. Let's count the number of passes, where a pass happens when a larger number moves from the left of a smaller number to the right of that number. This can happen in 1 swap of
a
andb
, witha
larger and in the array to the left ofb
. It can also take 2 swaps ifa
is moved to the array withb
in one swap and then moves on in a later swap. To keep track of things correctly, count passes in halves in this case. To make counting easier, it also counts as a pass when two of the same number split up and then recombine.The array is fully sorted after
(2n choose 2)
passes, so the only question is how many passes can happen with one swap. Here's a simple example wherea
andc
are swapped:Now let's count the maximum number of passes that can have happened:
a > c
, we definitely get 1 full pass.a > b
, then we get 1/2 pass becausea
must have been left ofb
at some point.a > d
, then we get 1/2 pass becausea
will be right ofd
at some point.c < d
, then we get 1/2 pass becaused
must have been left ofc
at some point.c < b
, then we get 1/2 pass becauseb
will be right ofc
at some point.Therefore the best you can do on a swap is to get 3 passes (1 full and 4 halves).
Why is this not a complete answer?
I have no idea if the lower bound is always attainable! I don't think it is, and, despite several failed attempts, I can't code up an algorithm that achieves it.
这是我想到的一个直观的算法。它给出了我认为的最佳解决方案的建设性证明。
这是算法:
我尝试了 n= 4 5 6 7 9,它给出了与 badawi 相同的结果:
想法如下:
1:选择一个不在他最终位置的极值(从 1 或 n 开始)
2:找到最接近他最终位置的极值(在下面的示例中用箭头标记)
<强>3:
如果它是最大的元素,
则将其移动到另一侧并将该对中的所有最小元素向左移动,
否则
将其移动到另一侧并将每对中的所有最大元素向右移动。
注意:移位相当于用每对的较小(或最大)元素“冒泡”该值。
4:返回第 2 步,但如果您选择了其中一个大的,则选择其中一个小的,反之亦然。
它非常直观并且似乎有效:
示例 n=5:
总共 15 步。
第二个例子 n=7:
总数: 31
如果我不清楚,请随时问我问题。
用手做起来非常容易。你可以自己用 6 或 7 尝试一下或者编写一个算法。
我用 6 试了一下,结果是 23。
,如果是 7,则为 31,如果为 9,则为 53,手动计算需要一分钟,而无需计算任何内容
为什么这个解决方案是最佳的:
每次将一个大元素移动到另一侧时,您将这对中所有最小的一个移到左侧。
因此,移动所有大元素不会使您失去移动所有最小元素的任何移动。
你总是向“正确的方向”移动你的元素,
此外,为了移动极端的元素,你需要最少的移动次数。
(这是因为算法采用最接近他最后位置的极值,不会丢失任何移动)
对于小元素的推理是相同的。
希望我没有犯任何错误。
它证明 badawi 结果如您所料是最佳的。
Here is an intuitive algorithm I thought of. It gives a constructive proof of the optimal solution I think.
Here is the algorithm :
I tried it for n= 4 5 6 7 9 and it gave the same results as the one from badawi:
The idea is the following:
1: chose one extreme value that is not at his final place ( 1 or n to start)
2: find the extreme value which is the closest to his final position ( marked with an arrow in my example below)
3:
If it's among the largest elment,
then move it to the other side and shifht all smallest element of the pair to the left
otherwise
move it to the otherside and shift all the largest element of each pair to the right .
Note: shifting is equivqlent to "bubbling" this value with the smalles (resp largest) element of each pair.
4: go back to step 2, but if you chose one of the large take one of the small and vice versa.
It's pretty intuitive and it seems to work:
Example n=5:
Total 15 moves.
second example n=7:
total: 31
Don't hesitate to ask me questions if i'm not clear.
It's pretty easy to do it by hand. You can try it yourself with 6 or 7 or write an algorithm.
I tried it with 6 it gave 23.
, with 7 it gave 31 and with 9 it gave 53 , it takes one minute to calculate it by hand without computing anything
Why this solution is optimal :
Each time you move one large element to the opposite side, you move all the smallest one of the pair to the left.
So moving all the large element will not make you lose any move for the moving all smallest one.
You always move you element in "the right direction"
Moreover you for moving the extreme elements you make the minimum number of moves.
(this is because the algorithm takes the extreme value closest to his last position that no move is lost)
The reasonning is the same for small element.
Hope I didn't make any mistake .
It proves that badawi results were optimal as you expected.