Сумма частей массива - JavaScript - PullRequest
7 голосов
/ 24 июня 2019

Пытаясь решить эту проблему на codewars . В соответствии с задачей, части массива:

ls = [0, 1, 3, 6, 10]

ли

ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []

И нам нужно вернуть массив с суммами этих частей.

Итак, мой код выглядит следующим образом:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

console.log(partsSums([0, 1, 3, 6, 10]));

Проблема в том, что он хочет, чтобы мы добавили последнюю сумму 0, когда массив пуст. Итак, мы должны получить:

[20, 20, 19, 16, 10, 0]

вместо

[20, 20, 19, 16, 10]

Итак, я попробовал это:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
arrayOfSums.push(0);
return arrayOfSums;
}
console.log(partsSums([0, 1, 3, 6, 10]));

И это:

function partsSums(ls) {
  ls.push(0);
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

Но это вызвало ошибки тайм-аута выполнения на Codewars:

Тайм-аут выполнения (12000 мс)

Так я тоже попробовал:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > -1) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

Но теперь это вызывает ошибку типа:

TypeError: уменьшение пустого массива без начального значения

Я не понимаю, как получить 0 в массив, когда все значения были сдвинуты. Задача, по-видимому, требует 0 в качестве конечной «суммы» массива, даже если массив пуст. Но вы не можете уменьшить пустой массив - что еще я могу сделать здесь?

РЕДАКТИРОВАТЬ : Попытка добавления начального значения к методу уменьшения:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b, 0);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

К сожалению, этот тест по-прежнему не проходит:

ожидается, что [] будет глубоко равно [0]

Ответы [ 6 ]

10 голосов
/ 24 июня 2019

Нет причин вычислять сумму снова и снова.На длинном массиве это будет очень неэффективно (O (n²)) и может объяснить ваши ошибки тайм-аута.Вычислите сумму в начале, а затем вычтите каждый элемент из нее в цикле.

ls = [0, 1, 3, 6, 10]

function partsSums(ls) {
    let sum = ls.reduce((sum, n) => sum + n, 0)
    res  = [sum]
    for (let i = 1; i <= ls.length; i++){
        sum -= ls[i-1]
        res.push(sum )
    }
    return res
}
console.log(partsSums(ls))
4 голосов
/ 24 июня 2019

Еще одно решение, прошедшее все тесты:

function partsSums(ls) {
    let result = [0],
      l = ls.length - 1;
      
    for (let i = l; i >= 0; i--) {
        result.push(ls[i] + result[ l - i]);
    }
    return result.reverse();
}


console.log(partsSums([]));
console.log(partsSums([0, 1, 3, 6, 10])); 
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
1 голос
/ 24 июня 2019

Вот одна вещь, которую вы могли бы сделать

function partsSums(ls) {
  if(!ls.length) return [0];
  let prevTotal = ls.reduce((a,b) => a + b);
  return [prevTotal, ...ls.map(val => prevTotal -= val)]
}

console.log(partsSums([0, 1, 3, 6, 10]));
1 голос
/ 24 июня 2019

попробуйте это с рекурсией:

function partsSums(ls) {
  let sum = ls.reduce((a, b) => a + b, 0);
  return  ls.length > 0 ? [sum].concat(partsSums(ls.slice(1))) : [0];
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
1 голос
/ 24 июня 2019

Вы можете выполнить итерацию с конца и получить это значение плюс последнее вставленное значение набора результатов.

Этот подход работает с одним циклом и без предварительного расчета максимальной суммы.

function partsSums(ls) {
  var result = [0],
      i = ls.length;
      
  while (i--) {
      result.unshift(ls[i] + result[0]);
  }
  return result;
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

С push и reverse.

function partsSums(ls) {
  var result = [0],
      l = 0,
      i = ls.length;
      
  while (i--) result.push(l += ls[i]);
  return result.reverse();
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 24 июня 2019

Вы можете использовать цикл for с slice, а когда i == 0, вы можете нарезать len + 1, который вернет вам пустой массив, а сумма будет равна 0.

function partsSums(arr) {
  const res = [], len = arr.length
  for (let i = len; i > -1; i--) {
    res.push(arr.slice(-i || len + 1).reduce((a, n) => a + n, 0))
  }
  return res;
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));

Вы также можете использовать два двойных reduce и, если следующего элемента нет, нажмите ноль.

function partsSums(arr) {
  const sum = arr => arr.reduce((r, e) => r + e, 0);
  return arr.reduce((r, e, i, a) => {
    const res = sum(a.slice(i, a.length));
    return r.concat(!a[i + 1] ? [res, 0] : res)
  }, [])
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
...