Как найти наибольшую разницу в массиве

Предположим, что у меня есть массив целых чисел:

int[] A = { 10, 3, 6, 8, 9, 4, 3 };

Моя цель - найти наибольшую разницу между A [Q] и A [P] такими, что Q > P.

Например, если P = 2 и Q = 3, то

diff = A[Q] - A[P]
diff = 8 - 6
diff = 2

Если P = 1 и Q = 4

diff = A[Q] - A[P]
diff = 9 - 3
diff = 6

Так как 6 - наибольшее число между всеми различиями, то есть ответ.

Мое решение выглядит следующим образом (в С#), но оно неэффективно.

public int solution(int[] A) {

    int N = A.Length;
    if (N < 1) return 0;

    int difference;
    int largest = 0;

    for (int p = 0; p < N; p++)
    {
        for (int q = p + 1; q < N; q++)
        {
            difference = A[q] - A[p];
            if (difference > largest)
            {
                largest = difference;
            }
        }
    }

    return largest;
}

Как я могу улучшить это, чтобы он работал в O (N)? Спасибо!

Простое использование max и min не будет работать. Minuend (Q) должен появиться после Subtrahend (P).

Этот вопрос основан на проблеме "максимальной прибыли" в кодовости (http://codility.com/train/). Мое решение только набрало 66%. Это требует O (N) для оценки 100%.

Ответ 1

Следующий код работает в O (n) и должен соответствовать спецификации (предварительные тесты на кодирование были успешными):

public int solution(int[] A)
{
    int N = A.Length;
    if (N < 1) return 0;

    int max = 0;
    int result = 0;

    for(int i = N-1; i >= 0; --i)
    {
        if(A[i] > max)
            max = A[i];

        var tmpResult = max - A[i];        
        if(tmpResult > result)
            result = tmpResult;
    }

    return result;
}

Обновление:
Я представил его в качестве решения, и он набрал 100%.

Обновление 02/26/16:
В исходном описании задачи о кодовости указано, что "каждый элемент массива A является целым числом в пределах диапазона [0,1,000,000,000]".
Если бы отрицательные значения были бы допущены, код выше не вернул бы правильное значение. Это можно легко устранить, изменив объявление max на int max = int.MinValue;

Ответ 2

Здесь реализована реализация O (n) Java

public static int largestDifference(int[] data) {
    int minElement=data[0], maxDifference=0;

    for (int i = 1; i < data.length; i++) {
        minElement = Math.min(minElement, data[i]);
        maxDifference = Math.max(maxDifference, data[i] - minElement);
    }
    return maxDifference;
}

Ответ 3

После некоторых попыток я получаю следующее:

int iMax = N - 1;
int min = int.MaxValue, max = int.MinValue;
for (int i = 0; i < iMax; i++) {
    if (min > A[i]) min = A[i];                                     
    if (max < A[N - i - 1]){
      iMax = N - i - 1;
      max = A[iMax];
    }        
 }
 int largestDiff = max - min;

ПРИМЕЧАНИЕ. Я только что протестировал его в некоторых случаях. Если вы найдете какой-либо случай, в котором он не работает, сообщите мне в комментарии. Я постараюсь улучшить его или удалить ответ. Спасибо!

Ответ 4

  int FirstIndex = -1;
            int SecondIndex = -1;
            int diff = 0;

            for (int i = A.Length-1; i >=0; i--)
            {
                int FirstNo = A[i];
                int tempDiff = 0;
                for (int j = 0; j <i ; j++)
                {
                    int SecondNo = A[j];
                    tempDiff = FirstNo - SecondNo;
                    if (tempDiff > diff)
                    {
                        diff = tempDiff;
                        FirstIndex = i;
                        SecondIndex = j;
                    }
                }
            }

            MessageBox.Show("Diff: " + diff + "   FirstIndex: " + (FirstIndex+1) + "   SecondIndex: " + (SecondIndex+1));

Ответ 5

PHP-решение для MaxProfit задачи проверки кодовости, дающее 100/100, найденное в http://www.rationalplanet.com/php-related/maxprofit-demo-task-at-codility-com.html

function solution($A) {
    $cnt = count($A);
    if($cnt == 1 || $cnt == 0){
        return 0;
    }

    $max_so_far = 0;
    $max_ending_here = 0;
    $min_price = $A[0];

    for($i = 1; $i < $cnt; $i++){
        $max_ending_here = max(0, $A[$i] - $min_price);
        $min_price = min($min_price, $A[$i]);
        $max_so_far = max($max_ending_here, $max_so_far);
    }

    return $max_so_far;
}

Ответ 6

100% оценка JavaScript-решения.

function solution(A) {
  if (A.length < 2)
    return 0;

  // Init min price and max profit
  var minPrice = A[0];
  var maxProfit = 0;

  for (var i = 1; i < A.length; i++) {
    var profit = A[i] - minPrice;
    maxProfit = Math.max(maxProfit, profit);
    minPrice = Math.min(minPrice, A[i]);
  }
  return maxProfit;
}

Ответ 7

Решение Python

def max_diff_two(arr):
    #keep tab of current diff and min value
    min_value = arr[0]

    #begin with something
    maximum = arr[1] - arr[0]

    new_min = min_value

    for i,value in enumerate(arr):
        if i == 0:
            continue

        if value < min_value and value < new_min:
            new_min = value

        current_maximum = value - min_value
        new_maximum = value - new_min

        if new_maximum > current_maximum:
            if new_maximum > maximum:
                maximum = new_maximum
                min = new_min
        else:
            if current_maximum > maximum:
                maximum = current_maximum

    return  maximum

Ответ 8

100% для решения Javascript, используя более элегантный функциональный подход.

function solution(A) {
    var result = A.reverse().reduce(function (prev, val) {
        var max = (val > prev.max) ? val : prev.max
        var diff = (max - val > prev.diff) ? max - val : prev.diff
        return {max: max, diff: diff}
    }, {max: 0, diff: 0})
    return result.diff
}