Java 使用简单数组通过堆叠对数字进行排序?

Java 使用简单数组通过堆叠对数字进行排序?,java,arrays,algorithm,Java,Arrays,Algorithm,这是一个家庭作业问题(对不起,我知道这些问题是不受欢迎的),但我和老师都不知道如何有效地解决它,所以我想把它放在这里,看看so上的奇妙大脑是否能帮助我们解决问题 给出了一个未指定大小的数组,其中包含随机数。它必须按递增顺序排序。每个元素可以移动到相邻的空白区域,也可以移动到相邻较大元素的顶部。我需要编写一个方法,返回排序给定数组所需的最小移动次数 这个问题被贴上了“可选”的标签,因为老师意识到这个问题太难了,但我很好奇如何解决它。欢迎对任何大小的阵列提出任何建议(对于长度为3的阵列,恕我直言)

这是一个家庭作业问题(对不起,我知道这些问题是不受欢迎的),但我和老师都不知道如何有效地解决它,所以我想把它放在这里,看看so上的奇妙大脑是否能帮助我们解决问题

给出了一个未指定大小的数组,其中包含随机数。它必须按递增顺序排序。每个元素可以移动到相邻的空白区域,也可以移动到相邻较大元素的顶部。我需要编写一个方法,返回排序给定数组所需的最小移动次数

这个问题被贴上了“可选”的标签,因为老师意识到这个问题太难了,但我很好奇如何解决它。欢迎对任何大小的阵列提出任何建议(对于长度为3的阵列,恕我直言)

编辑:谢谢你指出这还不清楚。我用数组来表示一个假想的真实情况。让我们以硬币为例:它们都排成一行放在一张桌子上,只有指定数量的“空格”可以放进去。但它们可以放在相邻的较大硬币上,也可以滑到相邻的空白处(可能是一枚硬币在一堆硬币上移动而腾空的)。

我假设:

  • “排序”表示只剩下一个堆栈
  • 如果源堆栈中的最大数字小于目标堆栈中的最小数字,我们只能将一个堆栈移动到另一个堆栈上(或者等效地:堆栈必须以较小的数字在顶部排序,并且将一个堆栈移动到另一个堆栈上会将整个堆栈移动到另一个堆栈的顶部)
然后,如果数组多次包含一个数字,显然没有解决方案。此外,数字的大小并不重要,只有他们的排名才重要。因此,在不丧失一般性的情况下,我们可以假设数组包含任意顺序的数字1..n。此外,要确定可能的移动,只有堆栈的顶部和底部才重要。因此,储存以下物品就足够了:

int[] bottom;
int[] top;
因为我们不能将堆栈分开,所以只有当
bottom[i]+1==top[j]
时,我们才能将堆栈i移到堆栈j上,否则我们将处于无法解决的状态。然而,如果我们处于一个游戏状态,这样的移动是可能的,那么最好立即执行,因为最终我们将不得不合并这些堆栈,移动单个堆栈比移动两个堆栈便宜


因此,唯一的自由度是如何以最少的移动次数将堆叠移动到位。目前,我没有看到明显的贪心算法,因此寻找最优解决方案可能需要将游戏的位置编码到一个图中,并对该图应用最短路径算法以找到最短的移动序列。

我决定通过一些假设/更改来检查这个问题,因为这让我更感兴趣:

1) 可以从桩的任何部分向左或向右移动图元

2) 您可以将一个元素堆叠到一堆上,无论它是更大、更小还是大小相同

3) 只要您在较小的数字之前从未遇到较大的数字,无论您如何遍历堆栈,数组都被视为已排序。所以1123是被排序的,但是1233不是,因为你可以把2解释为在1之前

这导致了一个非常有趣的问题,尽管有这样的公理:

公理A:你采取行动的顺序是不相关的,可以以任何方式重新安排,以获得相同的最终结果

Axiom Ab:如果数组中没有重复,那么只需将每个元素移向其最终位置即可

特别是,我开发了一个策略,希望您可以通过局部检查而不是递归/回溯来解决它,但我已经证明了这是徒劳的,稍后将展示它

我的策略是:

1) 从左到右查找翻转方向错误的对(数字越大,数字越小)

2a)当您找到一个时,如果有一个空白点或堆栈,右侧值可以立即填充,请将其向左移动,直到它填充为止

2b)否则,将左值向右移动一个。这会造成一种情况,即您有一堆不同的数字-首先,根据1)的逻辑将向右移动的值与其新右侧的值进行比较,然后再向下比较

2bii)将向下比较与对比较的处理方式相同-如果较低的值适合空点或堆栈,则将其向左移动,否则将较高的值向右移动并继续

示例:

1231->我们将1b向左移动,因为它将适合堆叠。11 2 3_

1321->我们将3向右移动,因为2不能放入空点/堆栈中。我们向左移动1b两次,因为它将适合于一个空点/适合于一个堆栈,然后向右移动3,因为2将不适合于一个空点/适合于一个堆栈。1 12 3

1132->我们将3向右移动,因为2不能向左移动。我们将2向左移动,因为它将适合一个空的位置。1 12 3

2311->我们将3向右移动,因为1a不能向左移动。我们向左移动了两次,因为它可以放在一个空位上。我们向左移动1a,因为它会堆叠。我们将2向右移动,因为1a1b不能向左移动。我们将1a2b向左移动,因为它将填补一个空白。11 2 3_

但是,这两个起始阵列出现了问题:

23411 10移动最佳,2r 3r 4r 1al*3 1bl*4使11 2 3 4

23111 9移动最佳,2r*3 3r*3 1bl 1cl*2使uu111 2 3-与23411策略相反!我们移动1的次数越少,移动23的次数越多,因为1的次数越多,所以我们会尽可能地减少移动次数

这表明我们不能仅仅通过简单的局部比较来解决这个新问题

我仍在思考这个问题,它似乎以一种有趣的方式非同寻常,我希望你们中的一些人喜欢和我一起思考:)

52413 // put smallest disk (1) on disk to the right 1 524_3 // shift disks to the left 1 position right (3 moves - moved 4, then 2, then 5) 1 _5243 // move 1 all the way left (4 moves) 15243 // same as above for 2 2 15_43 2 1_543 12543