假设有一个这样的队列(这些线条只是为了清晰起见,它们不代表任何东西):
[1,1,1,
2,2,2,
3,3,
4,
5]
我想将其分类为:
[1,2,3,4,5,
1,2,3,
1,2]
是否有算法可以解决这个问题?若然,它是如何解决的?
答案 0 :(得分:1)
如果你是用python编写的,请查看Counter类,它将列表转换为直方图类型。
from collections import Counter
l = [1,1,1,
2,2,2,
3,3,
4,
5]
c = Counter(l)
result = []
for i in range(max(c.values())):
result += [k for k,v in c.items() if v > i]
print(result)
答案 1 :(得分:0)
这个答案基于levis501s,但这似乎更简单(或至少不同)。与他的回答一样,这使用了python,尽管在其他高级语言中可以毫不费力地实现类似的功能。
from collections import Counter
c = Counter([1, 1, 1, 2, 2, 2, 3, 3, 4, 5])
while c:
run = list(c)
run.sort()
for e in run:
print(e)
c[e] -= 1
if c[e] == 0:
del c[e]
答案 2 :(得分:-1)
没有必要采用levis501s方法中描述的计算出现的方法,尽管可以说他的代码更简洁或更适合Python环境。
你可以通过重复循环来解决这个问题,直到所有原始元素都被排序并在循环中迭代整个列表以找到大于最后找到的数字的最小数字并将其弹出到该迭代的结果堆栈然后当没有更大的数字时终止内部循环。
如果你想命名它要使用的算法,它可能是直方图排序变体或者也许是桶排序变体..如果你挖掘平行排序算法,你可能会找到更接近描述你的问题的东西。
这是一个perl实现:
my @a=reverse(qw/ 1 1 1 2 2 2 3 3 4 5/); ## reverse order allows us to trim the array without messing up indexes
print qq{Source array = } . join(',',@a) . "\n";
my @bucket = ();
while ( $#a >= 0 )
{
my @bucket = (); ## start a new bucket
for ( my $i=$#a; $i>=0; $i-- )
{
if ( $#bucket==-1 && $a[$i]>0 || $bucket[$#bucket] < $a[$i] )
{
push @bucket, $a[$i];
splice @a, $i, 1; ## remove the element from the source data
}
}
print join(',',@bucket) . "\n"; ## display the constructed bucket list
}
或在perl中使用类似于levis501的方法
my @a = (1,1,1,2,2,2,3,3,4,5);
my $hist = {};
foreach my $i (@a )
{
$hist->{$i}++;
}
while ( scalar(%$hist)> 0)
{
foreach my $el ( sort keys %$hist )
{
$hist->{$el}--;
print qq{ $el };
delete $hist->{$el} if $hist->{$el}<1;
}
print "\n";
}