假设我们有以下一组数字表示随时间变化的值
1 2 3 10 1 20 40 60
现在我正在寻找一种算法来找到从一次到另一次的最高百分比增长。在上面的例子中,答案是对(1,60),增加了6000%。
到目前为止,我能想到的最好的算法是蛮力方法。我们使用一系列迭代来考虑所有可能的对:
第一次迭代:
1-2 1-3 1-10 .. 1-60
第二次迭代
2-3 2-10 2-1 ... 2-60
(等)
这具有复杂性O(n 3 )。
我一直在考虑另一种方法。找出所有严格增加的序列,并确定那些严格增加序列中的百分比增加。
有没有其他想法打击你们?如果我的想法错了,请纠正我!
答案 0 :(得分:2)
我可能误解了这个问题,但似乎你想要的只是最大和最小的数字,因为这两个数字都很重要。
while true:
indexOfMax = max(list)
indexOfMin = min(list)
list.remove(indexOfMax)
list.remove(indexOfMin)
if(indexOfmax < indexOfMin)
contine
else if(indexOfMax == indexOfMin)
return -1
else
SUCCESS
答案 1 :(得分:0)
根据我的理解(您的评论中没有更正我),您希望为所有a[i]/a[j]
最大化j <= i
。如果这是正确的,那么对于每个i
,我们只需要知道它之前的最小值。
int current_min = INFINITY;
double max_increase = 0;
for (int i = 0; i < n; ++i) {
current_min = min(current_min, a[i]);
max_increase = max(max_increase, a[i] / min);
}
答案 2 :(得分:0)
所以你只想比对每个数字,看看哪一对从第二个数字到第一个数字的比率最高?只需迭代两个循环(一个i = 0到n,一个内循环,j = i + 1到n)就会给你O(n ^ 2)。我想这实际上是你原来的解决方案,但你错误地说复杂性是O(n ^ 3)。它是n ^ 2。
但是你可以到达O(n log n)。拿你的列表,把它变成一个列表,其中每个元素都是一对(索引,值)。然后按该对的第二个元素对其进行排序。然后有两个指向列表的指针,一个来自左边(0到n-1),另一个来自右边(n-1到0)。找到第一对元素,使左元素的原始索引小于右元素的原始索引。完成。
1 2 3 10 1 20 40 60
becomes
(1,0) (2,1) (3,2) (10,3) (1, 4) (20, 5) (40, 6) (60,7)
becomes
(1,0) (1,4) (2,1) (3,2) (10,3) (20,5) (40,6) (60,7)
所以你的答案是60/1,从索引0到索引7。
如果这不是你想要的,那么如果你说出你的例子数字的正确答案会有所帮助。
答案 3 :(得分:0)
如果我正确理解你的问题,你正在寻找数组中的两个索引(i,j),其中i&lt; j具有最高比率A [j] / A [i]。如果是这样,那么您可以将其缩小为 this related problem ,它要求您找到i≤j的索引(i,j),使A [j] - A [i]为尽可能大。该问题具有非常快的O(n) - 时间,O(1) - 空间算法,也可以适应这个问题。直觉是解决数组的问题,只包含数组的第一个元素,然后是前两个元素,然后是前三个,等等。一旦你解决了数组前n个元素的问题,你有一个问题的整体解决方案。
让我们考虑如何做到这一点。最初,当您只考虑数组的第一个元素时,通过将元素与自身进行比较,您可以获得的最佳百分比增加为0%。现在,假设(归纳地)你已经解决了前k个数组元素的问题,并希望看到当你查看下一个数组元素时会发生什么。发生这种情况时,两个条件中的一个成立。首先,相对于前k个元素的最大百分比增加也可能是对第一个(k + 1)个元素的最大百分比增加。例如,如果(k + 1)st数组元素是一个非常小的数字,那么你很可能无法从前k个元素中的某个元素增加到该值。其次,最大百分比增加可能是从第一个k元素之一到第(k + 1)个st元素。如果是这种情况,最高百分比增长将是从第一个k元素中的最小元素到(k + 1)个元素。
结合这两种情况,我们得出最大百分比增加超过第一个k + 1元素的最大值
您可以通过迭代数组元素来跟踪两个值来实现这一点 - 您目前看到的最小值和最大化百分比增加的对。例如,对于
的原始示例数组1 2 3 10 1 20 40 60
算法可以这样工作:
1 2 3 10 1 20 40 60
min 1 1 1 1 1 1 1 1
best (1,1) (1, 2) (1, 3) (1, 10) (1, 10) (1, 20) (1, 40) (1, 60)
并且你输出(1,60)是最高的百分比增长。在不同的数组上,如下所示:
3 1 4 2 5
然后算法会像这样追踪: 3 1 4 2 5 分3 1 1 1 1 最佳(3,3)(3,3)(1,4)(1,4)(1,5)
你输出(1,5)。
这整个算法只使用O(1)空间并在O(n)时间内运行,这是一个非常好的解决方案。
或者,您可以考虑通过获取数组中所有值的对数来直接将此问题减少到最大单卖利润问题。在这种情况下,如果找到一对值,其中log A [j] - log A [i]最大化,这相当于(使用对数的属性)查找一对值log(A [j] / A [i])最大化。由于对数函数是单调递增的,这意味着您已找到一对值,其中A [j] / A [i]按预期最大化。