我问你关于这个问题的想法:
我有一个数组A,其中N个元素类型为double
(或者整数)。我想找一个复杂度小于O(N 2 )的算法来找到:
max A[i] - A[j]
对于1< j< = i< ñ。请注意,没有abs()
。我想到了:
您会有一些意见或想法吗?您是否可以指出一些很好的参考资料来培训或取得进展来解决此类算法问题?
答案 0 :(得分:8)
在阵列中进行三次扫描。首先从j=2
开始,到目前为止用 minimal 元素填充辅助数组a
。然后,从顶部i=n-1
向下扫描,从上到下填充(也从上到下)另一个辅助数组b
,其中最大元素到目前为止(从顶部开始) 。现在扫描两个辅助数组,寻找b[i]-a[i]
的最大差异。
这将是答案。总共O(n)
。你可以说它是一种动态编程算法。
编辑 作为优化,您可以消除第三个扫描和第二个数组,并通过维护两个循环变量 max-so-from-the-the-top 和 max-difference 。
关于如何解决这些问题的“指针”,你通常会尝试一些与你所写的一样的通用方法 - 分而治之,记忆/动态编程等。首先要仔细研究你所涉及的问题和概念。在这里,它是最大/最小。将这些概念区分开来,看看这些部分如何在问题的背景下结合,可能会改变它们的计算顺序。另一个是在你的问题中寻找隐藏的顺序/对称性。
具体来说,在列表中修复任意内部点k
,这个问题被简化为找到所有j
中最小元素之间的差异,使{{1} 1}},以及1<j<=k
s中的最大元素:i
。你在这里看到分而治之,以及拆分max / min的概念(即他们的渐进计算),以及各部分之间的相互作用。显示隐藏的顺序(k<=i<n
沿着数组),并且memoization有助于保存最大/最小值的中间结果。
任意点k
的修复可以被视为首先解决一个较小的子问题(“对于给定的k
...”),并查看是否有任何特殊的问题和它可以废除 - 通用 - 抽象结束。
有一种尝试首先制定和解决更大问题的技术,这样原始问题就是这个更大问题的一部分。在这里,我们想到找到 all 每个k的差异,然后从中找到最大值。
双重使用用于中间结果(用于比较特定的k
点,并用于计算下一个中间结果的每一个)意味着一些可观的节省所以,
答案 1 :(得分:4)
这应该可以在一次迭代中完成。 {1}为{&lt; 1} j&lt; =我应该与max(a[i] - a[j])
相同,对吗?因此,在迭代数组时,您必须跟踪最小的max[i=2..n](a[i] - min[j=2..i](a[j]))
,寻找最大的a[j]
。这样你只有一次迭代,j将小于或等于i。
答案 2 :(得分:1)
你只需要遍历数组找到max和min然后得到差异,所以最坏的情况是线性时间。如果对数组进行排序,您可以在恒定时间内找到差异,或者我是否会遗漏某些内容?
答案 3 :(得分:0)
Java实现以线性时间运行
public class MaxDiference {
public static void main(String[] args) {
System.out.println(betweenTwoElements(2, 3, 10, 6, 4, 8, 1));
}
private static int betweenTwoElements(int... nums) {
int maxDifference = nums[1] - nums[0];
int minElement = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] - minElement > maxDifference) {
maxDifference = nums[i] - minElement;
}
if (nums[i] < minElement) {
minElement = nums[i];
}
}
return maxDifference;
}
}