假设我们有一个包含整数的列表,我们需要找到最小值和最大值。最好的方法是什么?我可以想到以下内容:
如果读取次数远高于写入次数;保持列表排序。每当添加一个数字时;以排序方式添加它。现在要获取最小值和最大值,我们可以获取此列表的第一个和最后一个元素。
如果写入次数高于读取次数;迭代列表并返回结果。但这是 O(n),看起来很昂贵。
还有其他更好的方法吗?
假设我们有一个包含整数的列表,我们需要找到最小值和最大值。最好的方法是什么?我可以想到以下内容:
如果读取次数远高于写入次数;保持列表排序。每当添加一个数字时;以排序方式添加它。现在要获取最小值和最大值,我们可以获取此列表的第一个和最后一个元素。
如果写入次数高于读取次数;迭代列表并返回结果。但这是 O(n),看起来很昂贵。
还有其他更好的方法吗?
假设您可以观察到列表的任何突变,您可以存储(缓存)最小值和最大值,并可能在添加/删除数字时更新缓存的值。此时,列表的顺序无关紧要。
您可以为此使用 Collection.max() 和 Collection.min() 静态方法...
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html
使用 SortedSet 使集合自动排序。
我会提出一个有趣的想法:
假设您确实经常删除,尽管读取次数多于写入次数,您可能会保存一个项目数组(表示整数的对象,其中有两个对已添加项目的最小值和最大值的引用)并缓存了对先前最小值和最大值的引用(与@akaIDIOT 解决方案的区别在于这只是参考)。
堆栈中的每个值都指向前一个最大值和前一个最小值。
添加项目也需要 O(1),找出最小值和最大值也需要 O(1)。
更新中描述了删除项目:
缺点是更多的内存消耗。
如果此解决方案有误,我将删除它,如果您发现任何问题,请发表评论,无需投反对票!
更新
@akaIDIOT 在他的评论中提到了一个我错过的案例。如果您有多个最大值或最小值怎么办。
在这种情况下和其他情况下,删除最大值将需要更新指向它的所有对象,这将是最大 O(n),但我认为平均而言它仍将保持 O(1)。如果所有值都是不同的,这将始终是 O(1)
您还可以使用min/max heap
类似的数据结构(红黑树)来保留整数。获取最小值/最大值需要O(1)
时间,插入新元素需要O(log n)
时间。
假设您支持从列表中删除整数,无论哪个更高(读取或写入),拥有排序列表会使事情变得更容易并提供更好的性能。
您可以拥有一个维护 Min 和 Max 值的自定义列表。这将为您提供 O(1) 插入,O(1) 读取 Min 和 Max,以及 O(N) 删除,但仅在您删除 min 或 max 的情况下。
伪代码:
public MinMaxList
{
property Min;
property Max;
method Add (int newValue)
{
if (Min is null OR newValue < Min)
Min = newValue;
if (Max is null OR newValue > Max)
Max = newValue;
}
method Delete (int value)
{
if (value = Min or value = Max)
//Rescan list to determine new Min and Max values. This is O(N).
}
}