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

Добейтесь исключительных успехов в программировании интервью, решая по одной задаче каждый день.

Вопрос 1

Учитывая отображение a = 1, b = 2, … z = 26 и закодированное сообщение, посчитайте, сколько способов его можно расшифровать.

Например, сообщение ‘111’ даст 3, поскольку его можно расшифровать как ‘aaa’, ‘ka’, and ‘ak’.

Можно предположить, что сообщения поддаются декодированию. Например, ‘001’ не допускается.

Решение

Во-первых, мы определяем функцию isDecodable(message), которая возвращает 1, если сообщение может быть декодировано, иначе 0.

function isDecodable(message) {
    for (let i = 0; i < message.length; i++) {

    var parsed = parseInt(message[i], 10)
        if (isNaN(parsed)) {
            return false
        }
        if ((parsed > 0 && parsed < 27) != true) {
            return false
        }
    }
    return true
}

Далее мы предполагаем, что сообщения являются декодируемыми. Для решения проблемы в этом случае мы используем решение на основе рекурсии.

Если длина строки равна 1, всегда есть 1 способ ее декодирования, так что это наш базовый случай.

'1':
    ['1']
----------
F('1') = 1if (message.length <=1) {
    return 1
}

Если длина равна 2, у нас всегда есть 1 способ со всеми цифрами отдельно, плюс один, если число меньше, мы также используем этот способ как базовый.

'12':
    ['1', '2']
    ['12']
---------------------
F('12') = f('12') + 1

Если длина равна 3, мы можем использовать результаты предыдущих вычислений, потому что мы уже знаем, как работать с более короткими строками.

F('123') = f('1') * F('23') + F('12') * f('3') = 3

Наконец, все последующие случаи могут быть рассчитаны таким образом.

F('4123') = f('4') * F('123') + f('41') * F('23') = 3

Окончательный исходный код этой задачи

function decode_cnt_no_zero(message) {

  let length = message.length
    if (length <=1) {
        return 1
    }
    if (length >=2) {
        var parsed = parseInt(message.substring(0,2),10)
        if (parsed >=0 && parsed <= 26) {
            return (decode_cnt_no_zero(message.substring(1,length)) 
            + decode_cnt_no_zero(message.substring(2, length)))
        }
        return decode_cnt_no_zero(message.substring(1, length))
    }
}

Давайте попробуем изучить наше решение.

  • Результат декодирования 1 строки равен 1.
decode_cnt_no_zero(“1”)
<< 1
  • Результат декодирования 12-й строки равен 2.
decode_cnt_no_zero(“12”)
<< 
  • Результат декодирования строки 123 равен 3.
decode_cnt_no_zero(“123”)
<< 3
  • Результат декодирования строки 4123 равен 3.
decode_cnt_no_zero(“4123”)
<< 3

Вопрос 2

Учитывая поток элементов, слишком большой для хранения в памяти, выберите случайный элемент из потока с одинаковой вероятностью.

Решение

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

const selectRandomizer = function () {
    let streamCount = 0
    let selected

    const rand = function (stream) {
        for (let i = 0; i < stream.length; i++) {
            streamCount++
            if (streamCount === 0) selected = stream[i]
            else if (Math.random() <= 1 / streamCount) {
                selected = stream[i]
            }
        }
        return selected
    }
    return rand
}

Вопрос №3

Строитель хочет построить ряд из N домов, которые могут быть K разных цветов. У него есть цель минимизировать затраты, гарантируя, что никакие два соседних дома не будут одного цвета.

Дана матрица N на K, где n-я строка и k-й столбец представляют стоимость строительства n-го дома k-го цвета, верните минимальную стоимость для достижения этой цели.

Решение

Возвращает минимальную стоимость строительства N домов K разных цветов, при этом никакие два соседних дома не могут быть одного цвета.

Вот решение с временной сложностью O(NKK) и пространственной сложностью O(NK).

const minCostHouseColorInitialSolution = function(costs) {
    if (costs.length === 0) return 0
  
    const n = costs.length
    const k = costs[0].length
  
    // 2d array with n length and k rows
    const dp = [...Array(n)].map(() => Array(k))
  
    // fill first row
    for (let col = 0; col < k; col++) {
      dp[0][col] = costs[0][col]
    }
  
    for (let row = 1; row < n; row++) {
      // Finding the lowest costs for each column in this row
      for (let col = 0; col < k; col++) {
        dp[row][col] = Number.MAX_SAFE_INTEGER
  
        for (let numCol = 0; numCol < k; numCol++) {
          // we dont want the same column, as that is 2 houses of same color
          if (numCol !== col) {
            dp[row][col] = Math.min(
              dp[row][col],
              dp[row - 1][numCol] + costs[row][col]
            );
          }
        }
      }
    }
  
    let minCost = Number.MAX_SAFE_INTEGER;
    // get minimum of last row in dp table
    for (let col = 0; col < k; col++) {
      minCost = Math.min(minCost, dp[n - 1][col])
    }
  
    return minCost
  }

Далее, по-прежнему O(NKK) временная сложность, но O(K) пространственная сложность.

const minCostHouseColorII = function (costs) {
    if (costs.length === 0) return 0

const n = costs.length
    const k = costs[0].length
    const dp1 = [] // the last row
    const dp2 = [] // the current row
    // start the first row of costs, as the last row, and build from the second row onwards
    for (let i = 0; i < k; i++) {
        dp1[i] = costs[0][i]
    }
    for (let row = 1; row < n; row++) {
        for (let j = 0; j < k; j++) {
            // Finding the lowest costs for each column in this row
            dp2[j] = Number.MAX_SAFE_INTEGER;
            for (let m = 0; m < k; m++) {
                if (m !== j) {
                    dp2[j] = Math.min(dp2[j], dp1[m] + costs[row][j])
                }
            }
        }
        // copy all the current row to last row
        for (let j = 0; j < k; j++) {
            dp1[j] = dp2[j]
        }
    }
    let minCost = Number.MAX_SAFE_INTEGER;
    for (let i = 0; i < k; i++) {
        minCost = Math.min(minCost, dp1[i])
    }
    return minCost
}

Наконец, вот лучшее решение с временной сложностью O(NK) и пространственной сложностью O(1).

const minCostHouseColorBest = function (costs) {
    if (costs.length === 0) return 0

const n = costs.length
    const k = costs[0].length
    let min1 = 0
    let min2 = 0
    let idx1 = -1
    for (let i = 0; i < n; i++) {
        let m1 = Number.MAX_SAFE_INTEGER
        let m2 = Number.MAX_SAFE_INTEGER
        let idx2 = -1
        for (let j = 0; j < k; j++) {
            let cost = costs[i][j]
            cost += j === idx1 ? min2 : min1
            if (cost < m1) {
                m2 = m1
                m1 = cost
                idx2 = j
            } else if (cost < m2) {
                m2 = cost
            }
        }
        min1 = m1
        min2 = m2
        idx1 = idx2
    }
    return min1;
}

Легко, верно?