renovations
This commit is contained in:
parent
4b8b168fd2
commit
c7d4c7e3ff
172 changed files with 869 additions and 244 deletions
|
@ -1,99 +0,0 @@
|
|||
# Подсказка (медленное решение)
|
||||
Можно просто посчитать для каждого элемента массива все суммы, которые с него начинаются.
|
||||
|
||||
Например, для `[-1, 2, 3, -9, 11]`:
|
||||
|
||||
```js
|
||||
// Начиная с -1:
|
||||
-1
|
||||
-1 + 2
|
||||
-1 + 2 + 3
|
||||
-1 + 2 + 3 + (-9)
|
||||
-1 + 2 + 3 + (-9) + 11
|
||||
|
||||
// Начиная с 2:
|
||||
2
|
||||
2 + 3
|
||||
2 + 3 + (-9)
|
||||
2 + 3 + (-9) + 11
|
||||
|
||||
// Начиная с 3:
|
||||
3
|
||||
3 + (-9)
|
||||
3 + (-9) + 11
|
||||
|
||||
// Начиная с -9
|
||||
-9
|
||||
-9 + 11
|
||||
|
||||
// Начиная с -11
|
||||
-11
|
||||
```
|
||||
|
||||
Сделайте вложенный цикл, который на внешнем уровне бегает по элементам массива, а на внутреннем -- формирует все суммы элементов, которые начинаются с текущей позиции.
|
||||
|
||||
# Медленное решение
|
||||
|
||||
Решение через вложенный цикл:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
function getMaxSubSum(arr) {
|
||||
var maxSum = 0; // если совсем не брать элементов, то сумма 0
|
||||
|
||||
for(var i=0; i<arr.length; i++) {
|
||||
var sumFixedStart = 0;
|
||||
for(var j=i; j<arr.length; j++) {
|
||||
sumFixedStart += arr[j];
|
||||
maxSum = Math.max(maxSum, sumFixedStart);
|
||||
}
|
||||
}
|
||||
|
||||
return maxSum;
|
||||
}
|
||||
|
||||
alert( getMaxSubSum([-1, 2, 3, -9]) ); // 5
|
||||
alert( getMaxSubSum([-1, 2, 3, -9, 11]) ); // 11
|
||||
alert( getMaxSubSum([-2, -1, 1, 2]) ); // 3
|
||||
alert( getMaxSubSum([1, 2, 3]) ); // 6
|
||||
alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
|
||||
```
|
||||
|
||||
Такое решение имеет [оценку сложности](http://ru.wikipedia.org/wiki/%C2%ABO%C2%BB_%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B5_%D0%B8_%C2%ABo%C2%BB_%D0%BC%D0%B0%D0%BB%D0%BE%D0%B5) O(n<sup>2</sup>), то есть при увеличении массива в 2 раза алгоритм требует в 4 раза больше времени. На больших массивах (1000, 10000 и более элементов) такие алгоритмы могут приводить к серьёзным "тормозам".
|
||||
|
||||
# Подсказка (быстрое решение)
|
||||
|
||||
Будем идти по массиву и накапливать в некоторой переменной `s` текущую частичную сумму. Если в какой-то момент s окажется отрицательной, то мы просто присвоим `s=0`. Утверждается, что максимум из всех значений переменной s, случившихся за время работы, и будет ответом на задачу.
|
||||
|
||||
**Докажем этот алгоритм.**
|
||||
|
||||
В самом деле, рассмотрим первый момент времени, когда сумма `s` стала отрицательной. Это означает, что, стартовав с нулевой частичной суммы, мы в итоге пришли к отрицательной частичной сумме -- значит, и весь этот префикс массива, равно как и любой его суффикс имеют отрицательную сумму.
|
||||
|
||||
Следовательно, от всего этого префикса массива в дальнейшем не может быть никакой пользы: он может дать только отрицательную прибавку к ответу.
|
||||
|
||||
# Быстрое решение
|
||||
|
||||
```js
|
||||
//+ run
|
||||
function getMaxSubSum(arr) {
|
||||
var maxSum = 0, partialSum = 0;
|
||||
for (var i=0; i<arr.length; i++) {
|
||||
partialSum += arr[i];
|
||||
maxSum = Math.max(maxSum, partialSum);
|
||||
if (partialSum < 0) partialSum = 0;
|
||||
}
|
||||
return maxSum;
|
||||
}
|
||||
|
||||
|
||||
alert( getMaxSubSum([-1, 2, 3, -9]) ); // 5
|
||||
alert( getMaxSubSum([-1, 2, 3, -9, 11]) ); // 11
|
||||
alert( getMaxSubSum([-2, -1, 1, 2]) ); // 3
|
||||
alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
|
||||
alert( getMaxSubSum([1, 2, 3]) ); // 6
|
||||
alert( getMaxSubSum([-1, -2, -3]) ); // 0
|
||||
```
|
||||
|
||||
Информацию об алгоритме вы также можете прочитать здесь: [](http://e-maxx.ru/algo/maximum_average_segment) и здесь: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem).
|
||||
|
||||
Этот алгоритм требует ровно одного прохода по массиву, его сложность имеет оценку `O(n)`.
|
Loading…
Add table
Add a link
Reference in a new issue