Ответы пользователя по тегу Алгоритмы
  • Как реализовать Алгоритм Решето Эратосфена от определенного числа, до данного?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Решето Эратосфена всегда начинается с 2. Его принцип - на каждом шаге находим следующее невычеркнутое число, оно является простым. Для построения массива от 900000000 до 1000000000 необходимо вычеркнуть из этого массива все кратные простым числам от 2 до 500000000, а для этого надо эти простые найти.
    Ответ написан
    1 комментарий
  • Как распределить значение по ячейкам примерно равномерно?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    function distribute(arr, val) {
      let n = arr.length;
      let dVal = val;
      while (dVal > 0) {
        let d = dVal / n;
        dVal = 0;
        for (let i = 0; i < arr.length; i += 1) {
          if (arr[i] === 1) {
            continue;
          }
          arr[i] += d;
          if (arr[i] < 1) {
            continue;
          }
          dVal += arr[i] - 1;
          arr[i] = 1;
          n -= 1;
          if (n === 0) {
            return undefined;
          }
        }
      }
      return arr;
    }
    Ответ написан
    2 комментария
  • Как оптимальнее определить, сколько существует чисел с заданными количеством и суммой цифр?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    function find(sum, n, m) {
      if (n === 1) {
        return [`${sum}`];
      }
      const result = [];
      const min = Math.max(m, Math.floor(sum - (n - 1) * 9));
      const max = Math.floor(sum / n);
      for (let i = min; i <= max; i += 1) {
        find(sum - i, n - 1, i).forEach((el) => result.push(`${i}${el}`));
      }
      return result;
    }
    
    function findAll(sum, n) {
      if (sum > n * 9 || sum < n) {
        return [];
      }
      const result = find(sum, n, 1);
      return [result.length, result[0], result.pop()];
    }

    На самом деле первый и последний элемент можно получить без формирования всех вариантов, но вот насчёт количества я не уверен.
    Ответ написан
    Комментировать
  • Какая сложность алгоритма из блоков switch?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    O(1). У вас линейный код, циклов в нём нет.
    Ответ написан
    Комментировать
  • Как решить задачу линейным алгоритмом?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    1 ⩽ i ⩽ n
    Ответ написан
    Комментировать
  • Как ускорить алгоритм скользящего среднего?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    const movingAverage = (data, windowSize) => {
      let sum = data.slice(0, windowSize).reduce((acc, cur) => acc + cur, 0);
      const result = [sum / windowSize];
      for (let i = windowSize; i < data.length; i += 1) {
        sum = sum - data[i - windowSize] + data[i];
        result.push(sum / windowSize);
      }
      return result;
    };
    console.log(movingAverage([9, 3, 2, 0, 1, 5, 1, 0, 0], 3));
    // Array(7) [ 4.666666666666667, 1.6666666666666667, 1, 2, 2.3333333333333335, 2, 0.3333333333333333 ]
    Ответ написан
    2 комментария
  • Как проверить вхождение диапазона дат в определенный диапазон?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Когда диапазоны НЕ пересекаются? Когда один из них идёт после другого. То есть, первый диапазон заканчивается раньше, чем начинается второй или наоборот, второй заканчивается раньше, чем начинается первый. Запишем формально:
    $isNotOverlapped = $range2start > $range1end || $range1start > $range2end;

    Когда диапазоны пересекаются? Очевидно, что нам просто нужна инверсия предыдущего условия.
    $isOverlapped = !($range2start > $range1end || $range1start > $range2end);

    Но, если вспомнить булеву алгебру, то !(A || B) = !A && !B. Значит можем записать:
    $isOverlapped = $range2start <= $range1end && $range1start <= $range2end;
    Ответ написан
  • Правильно ли я реализовал сортировку timsort на php?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Неверно от начала, до конца.
    https://ru.wikipedia.org/wiki/Timsort
    Ответ написан
    Комментировать
  • Какая есть литература по конечным автоматам?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Посмотрите Книгу красного дракона и Введение в теорию автоматов.
    Когда конечный автомат переходит из одного состояния в другое, он выполняет какие-то действия?
    Может выполнять. Скажем, для распознавания ключевых слов достаточно знать, в каком допускающем состоянии оказался автомат, а вот для распознавания чисел уже необходимо при переходе выполнять дополнительные действия.
    Могут ли из одного состояния в другое, передаваться параметры, как из одной функции в другую?
    Кроме текущего состояния автомат может помнить какой-то набор параметров, не влияющих на переходы, но меняющийся при переходах. Пример - то же самое распознавание чисел. Автомат должен вычислить/запомнить знак, мантиссу и значение степени.
    Что это за входная строка такая? Можно ли обойтись без неё?
    Входная строка - это строка, состоящая из входных символов, которые управляют переходом автомата из состояния в состояние. Для чисел это будет набор символов +-123456789.e. Без входной строки автомату нечего будет распознавать.
    Ответ написан
    4 комментария
  • Задание из егэ по информатике.Что не так в моём коде?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Для решения такой задачи нужен предварительный анализ.
    Поскольку две части соединены логическим ИЛИ, то пока первое неравенство выполняется, истинность второго не имеет значения.
    Значит нам надо рассмотреть только ситуацию, когда первое неравенство ложно. Второе, при этом, должно быть истинно.
    Инвертируем первое условие, получим 2x + 3y ≤ 30.
    Чтобы найти минимальное значение A, при котором выполняется x + y ≤ A, мы должны найти максимум x + y, при котором 2x + 3y ≤ 30.
    Задача формализуется в
    max(x + y), 2x + 3y ≤ 30, x ∈ N, y ∈ N.
    Дальше, опять таки, можно рассуждать аналитически. Поскольку при увеличении x величина 2x + 3y растёт медленнее, чем при увеличении y, то максимальное значение x + y будет достигаться при максимальном значении x и минимальном значении y, удовлетворяющих неравенству. Поскольку минимальное значение y = 0, то получаем неравенство 2x ≤ 30, отсюда x = 15, x + y = 15, A = 15.
    А можно написать программу для перебора:
    a = 0;
    for (x = 0; 2 * x <= 30; x += 1) {
      for (y = 0; 2 * x + 3 * y <= 30; y += 1) {
        if (a < x + y) { 
          a = x + y;
        }
      }
    }
    Ответ написан
    Комментировать
  • Многомерная задача о рюкзаке?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Для 16 товаров проще всего сделать прямой перебор. Всего то 216 вариантов.
    Ответ написан
  • Каким образом отобразить реализацию кольцевой очереди на основе массива?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Ответ написан
    Комментировать
  • Как найти все завершённые пути на карте?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Задача сводится к поиску циклов в графе.
    https://neerc.ifmo.ru/wiki/index.php?title=%D0%98%...
    Ответ написан
    Комментировать
  • Как вернуть первые N максимальных элементов из массива без сортировки массива?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    const littleN = (arr, N) => arr.reduce(
      (acc, cur) => {
        const idx = acc.findIndex((el) => el.distance > cur.distance);
        if (idx !== -1) {
          acc.pop();
          acc.splice(idx, 0, cur);
        }
        return acc;
      },
      Array(N).fill(arr[0])
    );

    Но не уверен, что такая функция будет быстрее штатной сортировки, особенно при небольших массивах.
    Ответ написан
  • Как проверить введенное римское число на правильную запись?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Лень вспоминать C, держите вариант конечного автомата проверки римских цифр на JS.
    // Матрица переходов конечного автомата
    // -1 - допустимое конечное состояние
    // null - недопустимое состояние
    const dka = [
      [-1, 1, 5, 4, 10, 9, 15, 14], // 0
      [-1, 2, 5, 4, 10, 9, 15, 14], // 1
      [-1, 3, 5, 4, 10, 9, 15, 14], // 2
      [-1, null, 5, 4, 10, 9, 15, 14], // 3
      [-1, 8, 8, 7, null, null, null, null], // 4
      [-1, null, null, 6, 10, 9, 15, 14], // 5
      [-1, null, null, 7, 10, 9, 15, 14], // 6
      [-1, null, null, 8, 10, 9, 15, 14], // 7
      [-1, null, null, null, 10, 9, 15, 14], // 8
      [-1, null, null, 13, 13, 12, null, null], // 9
      [-1, null, null, null, null, 11, 15, 14], // 10
      [-1, null, null, null, null, 12, 15, 14], // 11
      [-1, null, null, null, null, 13, 15, 14], // 12
      [-1, null, null, null, null, null, 15, 14], // 13
      [-1, null, null, null, null, 18, 18, 17], // 14
      [-1, null, null, null, null, null, null, 16], // 15
      [-1, null, null, null, null, null, null, 17], // 16
      [-1, null, null, null, null, null, null, 18], // 17
      [-1, null, null, null, null, null, null, null], // 18
    ];
    
    // Алфавит
    const alphabet = 'MDCLXVI';
    
    // Разбивает строку на лексемы
    // (номера символов в алфавите, начиная с 1)
    // для отсутствующих символов возвращает 0
    const lexer = (str) => str.split('').map((l) => alphabet.indexOf(l) + 1);
    
    // Проверяет корректность числа в римской записи
    const check = (str) => {
      const lexems = lexer(str);
      let state = 0;
      let idx = 0;
      while (true) {
        const lex = lexems[idx] ?? 0;
        state = dka[state][lex];
        if (state === null) {
          return false;
        }
        if (state === -1) {
          return  idx === str.length;
        }
        idx += 1;
      }
    }
    Ответ написан
    2 комментария
  • Почему вставка элементов занимает такое время?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Классический массив - это непрерывная область памяти, заполненная данными в порядке возрастания индексов. Чтобы вставить элемент в массив необходимо перенести часть уже имеющихся элементов, освободив место под вставляемый. При вставке в случайное место матожидание количества переносимых элементов будет n/2, соответственно сложность алгоритма оценивается в O(n). Добавление элемента в конец массива имеет сложность O(1), если нам известен текущий размер и мы не выходим за пределы памяти, выделенной для хранения массива. Если памяти недостаточно, то придётся выделить новый блок, перенести туда весь массив и освободить старый блок памяти. Эта процедура тоже занимает O(n).

    Вставка в список зависит от того, есть ли у нас указатель на то место, куда надо вставить новый элемент. Если нет, то сначала необходимо выполнить поиск, который оценивается в O(n). Сама вставка, при этом, не требует перемещения других элементов и всегда выполняется за O(1).
    Ответ написан
    Комментировать
  • Как вырезать область изображения под контуром, Алгоритм?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Берём матрицу, размером с изображение, заполняем нулями. Отмечаем единицами точки, принадлежащие линиям контура.
    Добавляем в очередь точку, заведомо лежащую внутри контура и ставим в неё единицу.
    Забираем точку из очереди, добавляем в очередь соседей этой точки (слева, справа, сверху и снизу), в которых ещё не стоит единица, и ставим в них единицы. Повторяем, пока очередь не опустеет.
    Ответ написан
    1 комментарий
  • Как лучше обработать пробег автомобиля?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Интерполировать. Как именно - зависит от того, как используются автомобили.
    Если предположить, что пробег каждый день одинаковый, то берём общий пробег за интервал и делим на кличество дней в интервале. Затем либо сохраняем полученный средний пробег для каждого дня интервала, либо вычисляем пробег на конец месяца и сохраняем помесячно.
    Если, например, весь пробег только в будни, то, соответственно, вычисляем количество рабочих дней в интервале и делим на него. При раскидывании по дням, опять же, записываем нулевой пробег в выходные и средний в будни.
    Ответ написан
    4 комментария
  • Сортировка слиянием с выводом границ. Как реализовать?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Комментировать
  • Проблемой с программой сортировки случайных списков. Поможете?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    У вас неэффективно написана сортировка.
    При правильной сортировке пузырьком в худшем случае будет (N2-N)/2 итераций, у вас - N2.
    Ответ написан