Algorithm 高效排序置换
给定[n]的未排序排列,我想通过从左到右迭代来收集数字,以便对预排列(1…n)进行排序。Algorithm 高效排序置换,algorithm,sorting,iterator,permutation,quicksort,Algorithm,Sorting,Iterator,Permutation,Quicksort,给定[n]的未排序排列,我想通过从左到右迭代来收集数字,以便对预排列(1…n)进行排序。 为了达到这个目标,我必须进行多少次迭代? 例如: 给定“3、7、4、2、10、8、9、1、6、5”,迭代次数为6。 在第一次迭代中,我将收集数字1 在第二次迭代中,我将收集数字2 在第三次迭代中,我将收集数字3,4,5 在第四次迭代中,我将收集数字6 在第五次迭代中,我将收集数字7,8,9 在第六次迭代中,我将收集数字10 我构建了一个简单的代码,用O(n^2)完成任务,但我需要它更高效,所以我认为这里缺少
为了达到这个目标,我必须进行多少次迭代?
例如:
给定“3、7、4、2、10、8、9、1、6、5”,迭代次数为6。
在第一次迭代中,我将收集数字1
在第二次迭代中,我将收集数字2
在第三次迭代中,我将收集数字3,4,5
在第四次迭代中,我将收集数字6
在第五次迭代中,我将收集数字7,8,9
在第六次迭代中,我将收集数字10 我构建了一个简单的代码,用O(n^2)完成任务,但我需要它更高效,所以我认为这里缺少一个技巧。
有什么建议吗?如果您知道在假设中给定了一个数组,其中肯定存在[n]排列的所有元素,那么我认为:
y[1..n]
1
到n
的一个循环中,搜索每个迭代中收集项目的未排序元素的初始数组x
,y[x[i]]:=x[i]
y
是一个带有O(n)的排序排列1
到n
的n-element整数表以任何给定方式无序排列
我想根据您的示例详细解释如何通过输入阵列只进行一次迭代就可以实现目标
让我们看一下初始数组:
x[] = { 3, 7, 4, 2, 10, 8, 9, 1, 6, 5 }
因此,让我们从零开始填充以下数组:
y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
现在,让以下有序列表中的每一项都是排序算法的迭代:
x[1]
,它等于3
——让我们把它写在结果表y
的第三位下:
y[3]:=3
(实际上是:y[x[1]:=x[1]
)
结果表现在如下所示
y[]={0,0,3,0,0,0,0,0,0}x[2]
,它等于7
,并重复以下步骤:
y[7]:=7
(实际上是:y[x[2]:=x[2]
)
结果表现在如下所示
y[]={0,0,3,0,0,0,7,0,0,0}x[3]
等于4
:
y[4]:=4
(实际上是:y[x[3]:=x[3]
)
结果表:
y[]={0,0,3,4,0,0,7,0,0,0}x[4]
等于2
:
y[2]:=2
(实际上是:y[x[4]:=x[4]
)
结果表:
y[]={0,2,3,4,0,0,0,7,0,0,0}x[5]
等于10
:
y[10]:=10
(实际上是:y[x[5]:=x[5]
)
结果表:
y[]={0,2,3,4,0,0,7,0,0,10}x[6]
等于8
:
y[8]:=8
(实际上是:y[x[6]:=x[6]
)
结果表:
y[]={0,2,3,4,0,0,7,8,0,10}x[7]
等于9
:
y[9]:=9
(实际上是:y[x[7]:=x[7]
)
结果表:
y[]={0,2,3,4,0,0,7,8,9,10}x[8]
等于1
:
y[1]:=1
(实际上是:y[x[8]:=x[8]
)
结果表:
y[]={1,2,3,4,0,0,7,8,9,10}x[9]
等于6
:
y[6]:=6
(实际上是:y[x[9]:=x[9]
)
结果表:
y[]={1,2,3,4,0,6,7,8,9,10}x[10]
等于5
:
y[5]:=5
(实际上是:y[x[10]:=x[10]
)
结果表:
y[]={1,2,3,4,5,6,7,8,9,10}y
是输入表x
的完全排序版本,它是通过10次迭代生成的(所以O(n)成本水平)。
无论n
有多大,给定的输入表有多无序,在采用这些特定假设的情况下,成本是恒定的,等于n
我希望我没有误解你的问题。既然你已经知道结果,我不清楚你在“整理”什么。你在寻找什么样的结果——关于在每次迭代中“收集”哪些数字的信息,如你在Q中所示?在本例中,下面是一个简单的Python 2实现示例:
target = 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
def do_permut(targ):
look_for = 1
iter_num = 1
while look_for != len(targ) + 1:
print 'Iteration', iter_num, ':',
for item in targ:
if item == look_for:
print item,
look_for += 1
print
iter_num += 1
do_permut(target)
然而,任务不可避免地是O(N平方)——记住,大O代表最坏的情况!对于N个数字,您最多可以进行N次迭代(当targ
从开始就进行反向排序时,最坏的情况就是实现了这一点),因此,N个平方。您可以通过收集以前在迭代过程中看到的一组数字,并在look_for
位于该组时中断,来稍微优化每个迭代,但这只(大致)使每个迭代的工作量减半,因此仍然是O(N平方)
如果你能更好地解释你期望从你的工作中得到什么样的结果和产出,我们可能会提供更多帮助
出于好奇,这里有一个具有上述“改进”的版本,并且还有一个健全性检查,以确保如果传递的序列不是[1:n)
的排列,它会引发异常,而不是永远循环
target = 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
def do_permut(targ):
look_for = 1
iter_num = 1
while look_for != len(targ) + 1:
print 'iteration', iter_num, ':',
seen = set()
found_in_iter = 0
for item in targ:
seen.add(item)
if item == look_for:
print item,
found_in_iter += 1
look_for += 1
if look_for in seen:
break
print
if not found_in_iter:
raise ValueError('missing: %s' % look_for)
iter_num += 1
do_permut(target)
反转p
def iterations(perm):
invperm = [None] * len(perm)
for i in range(len(perm)): # yes, we could use enumerate
invperm[perm[i] - 1] = i
count = 1
for i in range(1, len(perm)):
count += invperm[i - 1] > invperm[i]
return count
Given : 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
x : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
#!/usr/bin/perl
if ($#ARGV < 0) { # with no arguments
@data = (3, 7, 4, 2, 10, 8, 9, 1, 6, 5);
}
else {
@tmp = (1..$ARGV[0]);
while(@tmp) {
push(@data, splice(@tmp, rand($#tmp), 1));
}
}
$key = 1;
while (@data) {
@remove = (); @remain = ();
printf "key = $key\t(@data) --> ";
foreach $i (@data) {
if ($i == $key) { # found
push(@remove, $i);
$key++;
}
else {
push(@remain, $i);
}
}
@data = @remain;
print "(@remove) & (@data)\n";
$count++;
}
print "Iteration = $count\n";
$ ./a.pl
key = 1 (3 7 4 2 10 8 9 1 6 5) --> (1) & (3 7 4 2 10 8 9 6 5)
key = 2 (3 7 4 2 10 8 9 6 5) --> (2) & (3 7 4 10 8 9 6 5)
key = 3 (3 7 4 10 8 9 6 5) --> (3 4 5) & (7 10 8 9 6)
key = 6 (7 10 8 9 6) --> (6) & (7 10 8 9)
key = 7 (7 10 8 9) --> (7 8 9) & (10)
key = 10 (10) --> (10) & ()
Iteration = 6
$ ./a.pl 10
key = 1 (2 1 4 8 5 9 3 6 7 10) --> (1) & (2 4 8 5 9 3 6 7 10)
key = 2 (2 4 8 5 9 3 6 7 10) --> (2 3) & (4 8 5 9 6 7 10)
key = 4 (4 8 5 9 6 7 10) --> (4 5 6 7) & (8 9 10)
key = 8 (8 9 10) --> (8 9 10) & ()
Iteration = 4
$ ./a.pl 10
key = 1 (3 1 7 8 6 2 9 5 4 10) --> (1 2) & (3 7 8 6 9 5 4 10)
key = 3 (3 7 8 6 9 5 4 10) --> (3 4) & (7 8 6 9 5 10)
key = 5 (7 8 6 9 5 10) --> (5) & (7 8 6 9 10)
key = 6 (7 8 6 9 10) --> (6) & (7 8 9 10)
key = 7 (7 8 9 10) --> (7 8 9 10) & ()
Iteration = 5