有可能吗?如果没有,给定一个大小为n的数组,我怎么知道如果对数组进行排序更好?
答案 0 :(得分:8)
使用 未排序的数组,在子线性时间内无法执行此操作。由于您不知道哪个元素是最大和最小的,因此您必须全部查看它们,因此需要线性时间。
你会发现最好的排序会比这更糟糕,可能与n log n
相关,所以进行线性扫描会“更好”。
如果您允许存储更多信息,还有其他方法可以加快此过程。您可以使用以下规则存储最小值和最大值:
通过这样做,可能绝大多数检索最小/最大是恒定时间。只有在您删除了最小值或最大值时,下一次检索才需要一次检索的线性时间。
之后的下一次检索将再次成为恒定时间,因为您已计算并存储它们,假设您没有再次删除临时中的最小/最大值。
只有最大值的伪代码可以简单如下:
def initList ():
list = []
maxval = 0
maxcount = 0
在上面的初始化代码中,我们只需创建列表以及最大值和计数。也可以很容易地添加最小值和计数。
要添加到列表中,我们遵循以上规则:
def addToList (val):
list.add (val) error on failure
# Detect adding to empty list.
if list.size = 1:
maxval = val
maxcount = 1
return
# If no maximum known at this point, calc later.
if maxcount = 0:
return
# Adding less than current max, ignore.
if val < maxval:
return
# Adding another of current max, bump up count.
if val = maxval:
maxcount += 1
return
# Otherwise, new max, set value and count.
maxval = val
maxcount = 1
删除非常简单。只需删除该值即可。如果它是最大值,则减少这些最大值的计数。请注意,这只有在知道当前最大值时才有意义 - 如果不是,那么您已经处于必须计算它的状态,因此只需保持该状态。
计数变为零将表示最大值现在未知(您已全部删除):
def delFromList (val):
list.del (val) error on failure
# Decrement count if max is known and the value is max.
# The count will become 0 when all maxes deleted.
if maxcount > 0 and val = maxval:
maxcount -= 1
获得最大值就是知道何时需要计算(maxcount
为零时)。如果不需要计算,只需返回它:
def getMax ():
# raise exception if list empty.
error if list.size = 0
# If maximum unknown, calculate it on demand.
if maxcount = 0:
maxval = list[0]
for each val in list:
if val = maxval:
maxcount += 1
elsif val > maxval:
maxval = val
maxcount = 1
# Now it is known, just return it.
return maxval
所有伪代码都使用看似全局变量list
,maxval
和maxcount
。在正确设计的系统中,它们当然是实例变量,因此您可以并排运行多个列表。
答案 1 :(得分:5)
考虑到一般性问题:
我可以在子线性时间内找到未排序数组中的最大/最小值吗?
我无法想象任何能够实现这一目标的机制。
但是,如果您保留对最小值和最大值的引用并更新每个插入/追加/替换操作的值,则最小/最大查找的摊销成本可能非常便宜。
与简单的线性扫描相比,对数组进行排序非常,以找到最小值和最大值,因此只有在有其他好处时才进行排序。 (当然,插入排序可以提供非常类似的属性来更新每个插入/追加/替换操作的最小值和最大值,因此它可能是可以接受的。)
答案 2 :(得分:2)
对于未排序的数组,最小/最大复杂度为O(N)。没办法超越它。对于排序数组0(1)但排序为0 {N log N)。如果你需要搜索最小/最大只有一个或接近它,排序是没用的。但是,如果您多次执行此操作,请查看某些搜索结构(如Rb-tree或堆)以重新组织日期以避免搜索中的线性时间。
答案 3 :(得分:0)
在这个完整的答案中(使用C ++代码)我在这里找到了 - What is the best way to get the minimum or maximum value from an Array of numbers - com - 它清楚地表明总比较次数 3n / 2 - 2 如果n是偶数(对于奇数,常数是3/2)。
所以在忽略 2常数(限定符为3/2和-2)后对大n没有影响,它显然属于 O(n)并且它在复杂性方面是线性的,但在效率方面(如果我可以这么说)它是1.5n且非常优秀