← Назад к вопросам

Сумма чисел в диапазоне

2.0 Middle🔥 181 комментариев
#Node.js и JavaScript#Алгоритмы и структуры данных

Условие

Напишите функцию sumRange(start, end), которая возвращает сумму всех целых чисел в указанном диапазоне включительно:

function sumRange(start, end) {
  // Ваш код
}

console.log(sumRange(1, 5));   // 15 (1+2+3+4+5)
console.log(sumRange(5, 1));   // 15 (должна работать в обоих направлениях)
console.log(sumRange(-3, 3));  // 0 (-3-2-1+0+1+2+3)
console.log(sumRange(10, 10)); // 10

Оптимизация

Используйте формулу арифметической прогрессии для O(1) решения.

Что проверяется

  • Базовые алгоритмы
  • Математическая оптимизация
  • Обработка граничных случаев

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение: Сумма чисел в диапазоне

1. Наивное решение O(n)

function sumRangeNaive(start: number, end: number): number {
  let sum = 0;
  const min = Math.min(start, end);
  const max = Math.max(start, end);
  
  for (let i = min; i <= max; i++) {
    sum += i;
  }
  
  return sum;
}

console.log(sumRangeNaive(1, 5));   // 15
console.log(sumRangeNaive(5, 1));   // 15
console.log(sumRangeNaive(-3, 3));  // 0

Минусы: На диапазоне 1-1,000,000 требует 1M итераций

2. Оптимальное решение O(1) - Формула арифметической прогрессии

function sumRange(start: number, end: number): number {
  // Гарантируем, что start <= end
  const min = Math.min(start, end);
  const max = Math.max(start, end);
  
  // Формула: sum = n * (first + last) / 2
  // где n = количество элементов
  const count = max - min + 1;
  const sum = (count * (min + max)) / 2;
  
  return sum;
}

console.log(sumRange(1, 5));   // 15
console.log(sumRange(5, 1));   // 15
console.log(sumRange(-3, 3));  // 0
console.log(sumRange(10, 10)); // 10

3. Объяснение формулы

Пример: sumRange(1, 5)

Диапазон: 1, 2, 3, 4, 5
Сумма: 1 + 2 + 3 + 4 + 5 = ?

Парный метод (Гаусс):
  1 + 5 = 6
  2 + 4 = 6
  3    = 3
  ------
Итого: 3 пары по 6 + 3 = 6 + 6 + 3 = 15

Формула:
  n = 5 (количество элементов)
  first = 1, last = 5
  sum = n * (first + last) / 2
  sum = 5 * (1 + 5) / 2
  sum = 5 * 6 / 2
  sum = 30 / 2
  sum = 15 ✓

Пример: sumRange(-3, 3)

Диапазон: -3, -2, -1, 0, 1, 2, 3
Парный метод:
  (-3) + 3 = 0
  (-2) + 2 = 0
  (-1) + 1 = 0
  0       = 0
  -------
  Итого: 0

Формула:
  count = 3 - (-3) + 1 = 7
  sum = 7 * ((-3) + 3) / 2
  sum = 7 * 0 / 2
  sum = 0 ✓

4. Как работает диапазон

function sumRange(start: number, end: number): number {
  // Шаг 1: Определяем границы
  const min = Math.min(start, end);
  const max = Math.max(start, end);
  
  // Шаг 2: Считаем количество элементов
  // Если диапазон [min, max], то элементов = max - min + 1
  // Примеры:
  // [1, 5]: 5 - 1 + 1 = 5 элементов (1, 2, 3, 4, 5) ✓
  // [5, 5]: 5 - 5 + 1 = 1 элемент (5) ✓
  // [10, 15]: 15 - 10 + 1 = 6 элементов (10, 11, 12, 13, 14, 15) ✓
  const count = max - min + 1;
  
  // Шаг 3: Применяем формулу
  // sum = количество_элементов * (первый + последний) / 2
  const sum = (count * (min + max)) / 2;
  
  return sum;
}

5. Варианты с рекурсией

// Простая рекурсия O(n)
function sumRangeRecursive(start: number, end: number): number {
  if (start === end) {
    return start;
  }
  
  if (start > end) {
    return 0;
  }
  
  return start + sumRangeRecursive(start + 1, end);
}

// Мемоизация: кэширует результаты
const memo = new Map<string, number>();

function sumRangeMemo(start: number, end: number): number {
  const key = `${start}-${end}`;
  
  if (memo.has(key)) {
    return memo.get(key)!;
  }
  
  if (start === end) {
    return start;
  }
  
  const result = start + sumRangeMemo(start + 1, end);
  memo.set(key, result);
  return result;
}

6. Производительность

const large = 1_000_000;

console.time('Naive O(n)');
sumRangeNaive(1, large);
console.timeEnd('Naive O(n)'); // ~10ms

console.time('Formula O(1)');
sumRange(1, large);
console.timeEnd('Formula O(1)'); // <0.1ms

// На диапазоне 1 - 1,000,000:
// Сумма = 1,000,000 * 1,000,001 / 2 = 500,000,500,000

7. Математическая формула подробнее

Сумма арифметической прогрессии:

S = n * (a₁ + aₙ) / 2

где:
  S  = сумма
  n  = количество членов
  a₁ = первый член
  aₙ = последний член

Почему это работает: Если у нас есть последовательность: a₁, a₂, ..., aₙ То: S = a₁ + a₂ + ... + aₙ И: S = aₙ + aₙ₋₁ + ... + a₁

Складываем два выражения: 2S = (a₁ + aₙ) + (a₂ + aₙ₋₁) + ... Каждая скобка = (a₁ + aₙ), таких скобок n штук 2S = n * (a₁ + aₙ)

S = n * (a₁ + aₙ) / 2

8. Edge cases

console.log(sumRange(5, 1));      // 15 (обратный диапазон)
console.log(sumRange(10, 10));    // 10 (один элемент)
console.log(sumRange(-5, -1));    // -15 (отрицательные)
console.log(sumRange(-2, 2));     // 0 (симметричные)
console.log(sumRange(0, 0));      // 0
console.log(sumRange(-1000, 1000)); // 0

9. Альтернативная реализация (без Math.min/max)

function sumRange(start: number, end: number): number {
  // Гарантируем start <= end
  if (start > end) {
    [start, end] = [end, start]; // Swap
  }
  
  const count = end - start + 1;
  return (count * (start + end)) / 2;
}

10. Тестирование

test('sumRange базовые случаи', () => {
  expect(sumRange(1, 5)).toBe(15);   // 1+2+3+4+5
  expect(sumRange(5, 1)).toBe(15);   // обратный
  expect(sumRange(-3, 3)).toBe(0);   // симметричный
  expect(sumRange(10, 10)).toBe(10); // один элемент
});

test('sumRange отрицательные диапазоны', () => {
  expect(sumRange(-5, -1)).toBe(-15); // -5-4-3-2-1
  expect(sumRange(-2, 2)).toBe(0);    // -2-1+0+1+2
});

test('sumRange большие диапазоны', () => {
  // Сумма 1 до 1000
  expect(sumRange(1, 1000)).toBe(500500);
});

Выводы

  • Наивное: O(n) время, O(1) память — медленно на больших диапазонах
  • Формула: O(1) время, O(1) память — идеально! ✓
  • Ключ: Знание математических формул критично для оптимизации
  • Нужно уметь переходить от итеративного решения к математическому