我有一个算法问题:
给定大小为N的数组(假设所有元素都是整数),找到最大的drop(不一定是连续的):max {array [i] -array [j]},其约束为:i> j .
简单的解决方案是两个循环并遍历i和j的所有可能值,但时间复杂度为O(n * n) .
我认为一个改进的解决方案是首先映射数组的索引,对数组进行排序,然后遍历数组以找到最大的丢弃 . 这种复杂性是O(nlogn) .
有线性时间复杂度的解决方案吗?如何?
PS:我曾经想过一个线性解决方案:创建两个额外的数组,一个是从开始到结束记录给定数组的最大值,另一个是从结尾到开始的最小值 . 然后,通过两个阵列一通 . 然而,有人认为不正确并占用太大的空间 . 所以我想知道一个更好的解决方案 . - lijuanliu
5 回答
创建新的2个数组:
现在,迭代辅助阵列并找到最大差异
max[i] - min[i]
这需要总共3次迭代,因此
O(n)
.Proof of correctness (guidelines):
让最大的下降是从索引
i
到索引j
,其中i<j
:然后,
max[i] >= arr[j]
(因为我们已经通过了它),以及min[i] <= arr[i]
- 因此max[j] - min[j] >= arr[i] - arr[j]
,算法提供的答案至少和最优答案一样好 .另外,由于最大跌幅是
i,j
,因此不能有k<j
这样的arr[k] < arr[i]
,因为那时最大跌幅将是从arr[k]
到arr[j]
. 相似 - 由于同样的原因,arr[k] < arr[j]
不能k>j
,因而max[j]-min[j] <= arr[i] - arr[j]
从上面我们可以得出结论
max[j]-min[j] = arr[i] - arr[j]
. 所有留给一个正式的完整证明是显示每个k
你得到max[k]-min[k] <= max[j] - min[j]
,这确实是这样,否则有一些u<k
,v>k
这样max[k]=arr[u], min[k]=arr[v]
,你得到arr[u] - arr[v] > arr[i] - arr[j]
,这与i,j
是的事实相矛盾最大跌幅 .QED
你需要跟踪两件事:
您所拥有的最大数量似乎是元素i,并且相对于最大数字(即i之前的最大数量减去元素i),您看起来最大的数量 . 这将是O(n)的时间和O(1)的空间 .
这个问题正是"stock buying/selling"面试的问题,解决方法可以在这里找到:Maximum single-sell profit
没有额外空间的O(n)解决方案:
我只能想到O(nlogn)但是这个虽然相同的复杂性应该比排序和找到最大的下降更快 .
你可以做的是计算O(n)中连续数字的差异然后问题将减少到找到连续子数组的MAX(和),这将是O(nlogn)