我需要一个排序算法,它在一个预先填充的单个数组上运行,并且仅限于执行一种类型的写操作:
O = 将项目X移动到索引Y.后续位置的元素移位1个位置。
必须针对尽可能少的操作O优化算法O.读取操作比写入操作便宜得多。临时助手名单也很便宜。
编辑:将其称为链接列表可能更为正确,因为它的行为,虽然实现对我来说是隐藏的。
背景
问题是我正在攻击Google API,它只允许我在他们的列表上执行此操作。该操作是Web服务调用。我想尽量减少通话次数。您可以假设排序程序(客户端)在启动之前在内存中有一个列表副本,因此不需要对服务执行读取操作 - 仅写入。在执行服务调用之前,您当然也可以在本地执行任意数量的临时列表操作,包括复制列表或使用现有的.NET排序函数。
我该怎么办?我可以在这里使用已知的算法吗?
尝试失败:
我已经实现了一个愚蠢的算法,但它并不适用于所有情况。当列表如下时,它运作良好:
列出A = [2,3,4,5,6,7,8,9,1]
它是这样的:
[1,2,3,4,5,6,7,8,9]
)......但是当列表是这样的时候,我遇到了麻烦:
列出B = [9,1,2,3,4,5,6,7,8]
[1,9,2,3,4,5,6,7,8]
)[1,2,9,3,4,5,6,7,8]
)答案 0 :(得分:9)
计算数组中增长最长的子序列。对序列中不存在的每个元素执行写操作。
编辑:添加示例
让输入数组中的数字为1 3 2 7 4 8 6 5 9
。最长的序列是1 2 4 6 9
。计算此序列时,会存储序列中出现的元素的索引。然后直接通过原始数组并找到序列中不存在的元素。在这种情况下,它们是3 7 8 5
。对于这些元素中的每一个执行写入操作,将它们放置在适当的位置。所以数组的修改顺序是:
1 2 3 7 4 8 6 5 9 (after writing 3 to appropriate position)
1 2 3 4 8 6 7 5 9 (after writing 7 to appropriate position)
1 2 3 4 6 7 5 8 9 (after writing 8 to appropriate position)
1 2 3 4 5 6 7 8 9 (after writing 5 to appropriate position)
答案 1 :(得分:3)
在本地对数组进行排序。保留原件的副本。
使用LCS distance计算原始数组和已排序版本之间的最佳编辑序列;这是Levenshtein distance的变体,不允许替换。 Levenshtein的动态编程算法的简化版本可用于计算LCS距离。查看diff
等程序的源代码,了解如何从动态编程表中获取编辑序列。
您现在拥有一个编辑序列,这意味着要执行的插入和删除列表将原始数组转换为已排序的版本。执行插入。 (您可以跳过删除,因为它们将由您的操作O执行,但请注意,数组中的索引会因此而发生变化,因此您必须对其进行补偿。)
答案 2 :(得分:2)
搜索最长的排序子序列,并将每个未排序的元素移动到正确的位置。
对于您的示例:
start: 2,3,4,5,6,7,8,9,1 (O = 0)
LSS: 2,3,4,5,6,7,8,9
step: 1,2,3,4,5,6,7,8,9 (O = 1)
start: 9,1,2,3,4,5,6,7,8 (O = 0)
LSS: 1,2,3,4,5,6,7,8
step: 1,2,3,4,5,6,7,8,9 (O = 1)
我的一个:
start: 9,3,1,7,2,8,5,6,4 (O = 0)
LSS: 1,2,5,6
step: 3,1,7,2,8,5,6,9,4 (O = 1)
LSS: 1,2,5,6,9
step: 1,7,2,3,8,5,6,9,4 (O = 2)
LSS: 1,2,3,5,6,9
step: 1,2,3,8,5,6,7,9,4 (O = 3)
LSS: 1,2,3,5,6,7,9
step: 1,2,3,5,6,7,8,9,4 (O = 4)
LSS: 1,2,3,5,6,7,8,9
step: 1,2,3,4,5,6,7,8,9 (O = 5)
您需要一种算法来识别LSS。您只需要使用它一次,拥有它之后,您可以在排序时将元素插入其中。
伪代码:
function O(oldindex, newindex):
# removes oldindex from list, shifts elements, inserts at newindex
function lss(list):
# identifies the LSS of a list and returns it in a cheap temporary list
function insert(index, element, list):
# inserts specified specified element into specified index in specified list
# elements at and after specified index are shifted down to make room
function sort(input):
lss_temp_list = lss(input) # get lss of input list
do until lss == input:
old = any(index where (input[index] not in lss)# item in input; not in lss
# getting new index is uglier
nl = min(X where (X > input[old] and X in lss))# next lowest element in lss
nh = max(X where (X < input[old] and X in lss))# next highest element in lss
new = any(index # index of next lowest/highest
where ((input[index + 1] == nl and nl exists)
or (input[index + 1] == nh and nh exists))
O(old, new) # list shift
il = min(index where (lss[index] > input[new]))# index of next lowest in lss
ih = max(index where (lss[index] < input[new]))# index of next highest in lss
i = any(X where (X == il or X == (ih + 1))) # index to insert element
insert(i, input[new], lss) # add new element to lss
repeat
return input
对于那种不可思议的伪代码风格表示抱歉,我试图让它变得足够窄,以免使代码块需要滚动条。