LeetCode #70 Восхождение по лестнице. Как ускорить мое решение?

У меня есть решение этой проблемы на LeetCode #70. Подъем по лестнице. Мое решение не проходит из-за того, что оно медленное...

Я добавил батут, используя преобразователи, и я добавил Memoization, что еще я могу добавить, чтобы ускорить это, чтобы фактически сократить время, необходимое для этой проблемы, мой код ниже, и заранее спасибо.

Описание на LeetCode:

Вы поднимаетесь по лестнице. Требуется n шагов, чтобы добраться до вершины.

Каждый раз вы можете подняться на 1 или 2 ступеньки. Сколькими различными способами вы можете подняться на вершину?

Примечание. Заданное n будет положительным целым числом.

Example 1:

Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps


Example 2:

Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step

Ссылка на проблему на LeetCode: https://leetcode.com/problems/climbing-stairs/


let cache = {};

const sumStairSteps = arr => arr.reduce((acc, cur) => acc + cur, 0);

const thunk = (fn, ...args) => {
    return () => fn(...args);
}

const climbStairsHelper2 = fn => {

    let thunk = fn();

    while (typeof thunk === "function") {
        thunk = thunk();
    }

    return thunk;
};

const climbStairs2 = (newStairSequence, ladderCount) => {
    const sum = sumStairSteps(newStairSequence);

    if (sum === ladderCount) {  cache[ladderCount] = cache[ladderCount] + 1; }


    if (1 + sum <= ladderCount) {
        climbStairsHelper2(thunk(climbStairs2, [ ...newStairSequence, 1 ], ladderCount));
    }

    if (2 + sum <= ladderCount) {
         climbStairsHelper2(thunk(climbStairs2, [ ...newStairSequence, 2 ], ladderCount));
    }
};

const climbStairs = n => {
        if (n in cache) return cache[n];
        cache[n] = 0;
        climbStairs2([], n);
        console.log(cache[n]);
        return cache[n];
};


person Gringo Jaimes    schedule 05.05.2020    source источник
comment
Что именно вы пытаетесь сделать здесь?   -  person CertainPerformance    schedule 05.05.2020
comment
Я пытаюсь увеличить скорость моего решения.   -  person Gringo Jaimes    schedule 05.05.2020
comment
Нет, я имею в виду, можете ли вы объяснить, для чего предназначен код, который вы разместили?   -  person CertainPerformance    schedule 05.05.2020
comment
Я использую Memoization с рекурсией, также я использую батут с переходниками, чтобы избежать исключения переполнения стека.   -  person Gringo Jaimes    schedule 05.05.2020
comment
Но какую проблему вы на самом деле пытаетесь решить?   -  person CertainPerformance    schedule 05.05.2020
comment
Добавил ссылку с дополнительным пояснением, прошу прощения за это.   -  person Gringo Jaimes    schedule 05.05.2020


Ответы (2)


Я не совсем понимаю подход, который вы здесь используете. Проблема на самом деле довольно проста: закодируйте наивное рекурсивное решение, затем запомните результаты. То есть, если вы посещаете ступеньку в тайнике, верните ее, иначе вычислите. Время выполнения линейно.

const climbStairs = (goal, curr=0, memo={}) => {
  if (goal < curr) {
    return 0;
  }
  else if (goal === curr) {
    return 1;
  }
  else if (curr in memo) {
    return memo[curr];
  }
  
  return memo[curr] = climbStairs(goal, curr + 1, memo) +
                      climbStairs(goal, curr + 2, memo);
};

console.log(climbStairs(50));

person ggorlen    schedule 05.05.2020
comment
Есть ли способ оптимизировать мое решение? - person Gringo Jaimes; 05.05.2020
comment
Конечно, вы можете отказаться от переходов, распределения, суммирования, дополнительных помощников и других ненужных шагов и наложить на заметку, как я показываю здесь, но я не уверен, насколько это поучительно, и кажется, что это приравнивается к переписыванию. Другими словами, я не вижу единого очевидного способа исправить код, но я также не очень понимаю фундаментальный подход. - person ggorlen; 05.05.2020
comment
Да, в общем, пришлось выкинуть в мусорку и переделать... - person Gringo Jaimes; 18.08.2020

Итак, вы хотите, чтобы решение было более оптимизированным.

Решение, которое вы сейчас обсуждаете, имеет линейное время выполнения, т. е. O(N), и принимается на LeetCode. Пока не будем говорить о пространственной сложности.

Эта проблема и категория этих проблем могут быть решены с помощью метода, называемого матричным возведением в степень, который имеет логарифмическое время выполнения, т. е. O(Log N)

Матричное возведение в степень очень хорошо описано по этой ссылке

https://discuss.codechef.com/t/building-up-the-recurrence-matrix-to-compute-recurrences-in-o-logn-time/570

person Dinkar Gahoi    schedule 13.06.2020