假定一个数组,其中每个元素也是一个正整数,没有重复且没有任何丢失的元素,如下所示:
{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:我需要遵循此过程(删除和插入元素,并在小组中进行思考),而不是其他更省时的方法,因为这将在现实世界中应用于对货架上的物品进行排序,并且带有较少数量的项目需要较少的操作次数,而不是计算或内存需求。
答案 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