排序数组时尽量减少插入次数

时间:2018-12-20 15:51:07

标签: arrays algorithm sorting

假定一个数组,其中每个元素也是一个正整数,没有重复且没有任何丢失的元素,如下所示:

{15, 1, 2, 6, 7, 8, 3, 4, 9, 5, 10, 13, 11, 12, 14}

考虑到每个元素的删除和插入(而不是交换),我如何找到最有效的移动(删除/插入)操作来对插入次数最少的列表进行排序。

我认为识别单个组是有帮助的,因为我可以更轻松地找到需要一起移动的内容:

{{15}, {1, 2}, {6, 7, 8}, {3, 4}, {9}, {5}, {10}, {13}, {11, 12}, {14}}

为此,我可以创建另一个数组,该数组的值与正确位置之间存在差异,以便于我轻松识别出哪些组以及哪些组与正确组最远。

{{14}, {-1, -1}, {2, 2, 2}, {-4, -4}, {0}, {-5}, {-1}, {1}, {-2, -2}, {-1}}

然后,从处于正确位置(最大差异)且元素数量较少的组中选择最远的组。因此,基于此,我可以看到{15}与正确值之间的距离为14,并且应该是第一个要移动的位置。我认为(我在这里猜测)我需要至少转移价值差异,因为我可以进入小组中间。重复此过程,我将{5}移到{6,7,8}之前,这移了6个空格,值和正确位置之间的差异更大,因为在正确的位置有一组。然后是{3,4},最后是{13},列表已排序。

我已经可以创建一个迭代方法来做到这一点。但是我认为这样做效率极低,因为我要处理大约200k的值,并在每组插入后重新计算它是一个糟糕的主意。

PS:我需要遵循此过程(删除和插入元素,并在小组中进行思考),而不是其他更省时的方法,因为这将在现实世界中应用于对货架上的物品进行排序,并且带有较少数量的项目需要较少的操作次数,而不是计算或内存需求。

2 个答案:

答案 0 :(得分:1)

最小化被移动元素的数量与最大化被移动的元素的数量相同。

由于您移动的任何元素都将保留其原始顺序,因此这些元素必须是所需排序数组的子序列。您可以使用通用算法来找到最长的子序列:

https://en.wikipedia.org/wiki/Longest_common_subsequence_problem https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/

然后删除所有不属于此子序列的元素,然后将其重新插入到它们属于的任何位置。

请注意,对于最长的单调递增子序列的这种特定情况,可以使用一些优化方法:

https://en.wikipedia.org/wiki/Longest_increasing_subsequence https://www.geeksforgeeks.org/longest-increasing-subsequence-dp-3/

答案 1 :(得分:0)

Create an integer array of size 16.  Call it fred.
Init all of the values to 0
Iterate your unsorted array.  
    use each value as a subscript into fred, setting the value to 1.

Pretend your unsorted array is empty.
Iterate fred.
    when you encounter a value of 1, that subscript needs to be inserted 
    back into your unsorted array.

Your unsorted array of size N is now sorted at a cost of N insertions