【问题标题】:Algorithm to find the largest drop in an array找到数组中最大下降的算法
【发布时间】:2013-02-07 19:34:08
【问题描述】:

我有一个算法问题:

给定一个大小为 N 的数组(假设所有元素都是整数),找到最大的下降(不一定是连续的):max{array[i]-array[j]} 有一个约束:i>j。

简单的解决方案是两个循环,遍历i和j的所有可能值,但时间复杂度为O(n*n)。

我认为一个改进的解决方案是首先映射数组的索引,对数组进行排序并遍历数组以找到最大的下降。这个复杂度是 O(nlogn)。

有线性时间复杂度的解决方案吗?怎么做?

PS:我曾经想过一个线性的解决方案:创建两个额外的数组,一个是记录给定数组从头到尾的最大值,另一个是从尾到头的最小值。然后,经过两个数组一关。但是,有人认为这不正确并且占用了太大的空间。所以我想知道一个更好的解决方案。 ——李娟流

【问题讨论】:

  • 啊,课程作业中的一个问题。你不应该更好地自己解决这个问题吗?
  • @arkascha:我曾经想过一个线性解决方案:创建两个额外的数组,一个是记录给定数组从头到尾的最大值,另一个是从头到尾记录最小值结束到开始。然后,通过两个数组一次。但是,有人认为这不正确并且占用了太大的空间。所以我想知道一个更好的解决方案。
  • 你没有明白我的意思 ;-)
  • 很难假设这个问题是针对家庭作业的。这是一个相对常见的编码挑战问题,也是展示巧妙算法设计如何显着提高运行时间的经典示例。

标签: arrays algorithm


【解决方案1】:

我只能想到 O(nlogn) 但这一个即使相同的复杂性应该比排序和找到最大的下降更快。

您可以做的是计算 O(n) 中连续数字的差异,然后问题将简化为找到连续子数组的 MAX(sum),即 O(nlogn)

【讨论】:

  • 当 i+1 和 j 之间有 k 且 array[k] > array[k-1] 时,这不起作用
  • 是的,因为您可以添加 (-) 数字并减少总和。这就是为什么它是 O(nlogn ) 而不是 O(n) 你需要遍历整个数组。说真的,为什么会投反对票?
【解决方案2】:

您需要跟踪两件事:

您似乎到元素 i 的最大数量,以及相对于最大数量的最大下降(即 i 之前的最大数量,减去元素 i)。这将是时间上的 O(n) 和空间上的 O(1)。

这个问题正是“股票买卖”的面试题,解决方法可以在这里找到:Maximum single-sell profit

【讨论】:

  • 是的,这个链接很有用。
【解决方案3】:

新建2个数组:

max[i] = max { arr[0], arr[1], ..., arr[i] }
min[i] = min { arr[n-1], arr[n-2], ..., arr[i] }
(max is the maximum from first to i, min is the minimum from i to last)

现在,迭代辅助数组并找到最大差异max[i] - min[i]

这需要 3 次迭代,因此是 O(n)

正确性证明(准则):

让最大的下降是从索引i 到索引j,其中i<j

  1. 然后,max[i] >= arr[j](因为我们已经通过了),还有 min[i] <= arr[i] - 因此max[j] - min[j] >= arr[i] - arr[j],和 算法提供的答案至少和 最佳。
  2. 另外,由于降幅最大的是i,j,所以不可能有k&lt;j 这样arr[k] &lt; arr[i],因为那时最大的下降将是 从arr[k]arr[j]。相似之处 - 不能有 k&gt;j 这样 arr[k] &lt; arr[j],出于同样的原因 - 因此max[j]-min[j] <= arr[i] - arr[j]

从上面我们可以得出结论max[j]-min[j] = arr[i] - arr[j]。剩下的就是一个正式的完整证明,证明对于每个k,你得到max[k]-min[k] &lt;= max[j] - min[j],情况确实如此,否则有一些u&lt;kv&gt;k,这样max[k]=arr[u], min[k]=arr[v],你就明白了arr[u] - arr[v] &gt; arr[i] - arr[j],这与 i,j 是最大跌幅的事实相矛盾。

QED

【讨论】:

  • @lijuanliu 是的,O(n) 额外空间
  • 我有个想法,辅助数组够不够? (只保留“min”数组)
  • @lijuanliu 基本上你可以修改方法,从最后一个到第一个,记住最小值,并为每个元素检查arr[i]-min &gt;= max_so_far - 如果是,它是新的最大值。不难看出,其实是之前O(n)空间版本的O(1)空间优化,证明会很相似。
【解决方案4】:
public static int maxDrop(int[]array){

    int maxDrop =0,drop=0,min=array[0];

    for(int i=1;i<array.length;i++){

        if(array[i]<min){
            min=array[i];
        }

        drop = array[i]-min;

        if(drop>maxDrop){
            maxDrop=drop;
        }

    }

    System.out.println(maxDrop);
    return maxDrop;

}

【讨论】:

  • 我认为有一个bug:对于输入{ 5, 21, 3, 22, 12, 7, 26, 14},上面的代码返回23而不是18。
【解决方案5】:

O(n) 没有额外空间的解决方案:

public int maxDrop(int[] a) {
    int max = a[0];
    int maxDrop = -1;
    for (int i = 0; i < a.length; i++) {
        if (max < a[i]) {
            max = a[i];
        }
        else {
            int drop = max - a[i];
            maxDrop = Math.max(maxDrop, drop);
        }
    }
    return maxDrop;
}

【讨论】:

    猜你喜欢
    • 2017-10-28
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多