我正在参加edx的cs50课程并且正在做pset3的黑客版本(实质上它是高级版本)。 基本上,程序将一个值作为命令行参数进行搜索,然后要求在数组中使用一堆数字。 然后它对该数组进行排序和搜索,以获取在命令行输入的值。 程序的实现方式,它使用伪随机数生成器来提供数组的数字。
任务是编写搜索和排序功能。 我已经有了搜索功能,但排序功能应该是O(n)。 在常规版本中,您应该使用O(n ^ 2)算法,这不是一个实现的问题。同样使用log n算法也不是问题。 但问题集特别要求大O(n)算法。
它提示说,因为数组中的数字不会是负数,并且不大于LIMIT(生成器输出的数字是模数&d;因此它们不大于65000) 。但是,这有助于使算法成为O(n)?
但计数排序算法,声称是一个可接受的解决方案,返回一个新的排序数组,而不是实际排序原始的数组,这与读取的pset规范相矛盾,因为这种返回类型的void意味着,此函数不得返回已排序的数组;它必须反而“破坏性地”#34;通过移动其中的值来对它传递的实际数组进行排序。'
另外,如果我们决定使用另一个循环将已排序的数组复制到原始数组上,并且有很多连续循环,我不确定排序函数是否可以被认为具有O的运行时间(n )了这是实际的pset,问题是关于排序部分。
如何实现这种算法的任何想法将不胜感激。没有必要提供实际的代码,而只是你可以在提供的条件下创建O(n)算法。
答案 0 :(得分:5)
它提示说,因为数组中没有数字 为负数,且不大于LIMIT(输出的数字 由发生器模数不高于65000)。但是怎么样 这有助于使算法成为O(n)。
该提示似乎直接指向counting sort。 您可以创建65000个存储桶并使用它们来计算每个数字的出现次数。 然后,您只需重新访问存储桶即可获得排序结果。
它利用了这样一个事实:
它的复杂性是O(n),因为这不是基于比较的排序,排序中的O(nlogn)下限不适用。一个非常好的可视化是here。
答案 1 :(得分:2)
正如@DarkCthulhu所说,数字排序显然是他们敦促你使用的。但你也可以使用基数排序。
这是一个特别简洁的基数2类型,利用与格雷码的良好连接。在您的应用程序中,它需要输入16次,每个数据位一次。对于大输入,计数排序可能更快。对于小的,基数排序应该是fster因为你避免初始化256K字节或更多的计数器。
请参阅this article for explanation。
void sort(unsigned short *a, int len)
{
unsigned short bit, *s = a, *d = safe_malloc(len * sizeof *d), *t;
unsigned is, id0, id1;
for (bit = 1; bit; bit <<= 1, t = s, s = d, d = t)
for (is = id0 = 0, id1 = len; is < len; ++is)
if (((s[is] >> 1) ^ s[is]) & bit)
d[--id1] = s[is];
else
d[id0++] = s[is];
free(d);
}