Pull to refresh

Решение нескольких задач от Amazon на примере JavaScript

Reading time4 min
Views8.4K


Доброго времени суток. Представляю вашему вниманию перевод статьи «Amazon Coding Interview Questions» автора Trung Anh Dang.

В этой статье автор приводит несколько (три, если быть точнее) задач от Amazon (как он утверждает) и свои варианты решений.

После ознакомления с условиями задачи, попробуйте решить ее самостоятельно. Затем сравните свое решение с авторским. Мои решения оказались близкими к авторским, но немного хуже. Если вам покажется, что ваше решение лучше, прошу поделиться им в комментариях.

Итак, поехали.

Задача № 1


Кодирование длин серий или кодирование повторов (run-length encoding) — это быстрый и простой способ кодирования строк. Суть этого алгоритма заключается в замене повторяющихся символов (серии) на один символ и число его повторов. Серией называется последовательность, состоящая из нескольких одинаковых символов. При кодировании строка одинаковых символов, составляющих серию, заменяется строкой, содержащей сам повторяющийся символ и количество его повторов.

Например, строка "AAAABBBCCDAA" после кодирования повторов будет выглядеть как "4A3B2C1D2A".

Реализуйте кодирование и декодирование повторов. Строка для кодирования состоит только из букв, не содержит чисел. Строка для декодирования является валидной.

Решение


Кодирование строки


Решение довольно простое:

const encoding_string = function(string) {
    if(string.length === 0) return ''
    
    let currChar = string.charAt(0)
    let count = 1
    let encoding = ''
    
    for(let i = 1; i < string.length; i++) {
        const char = string.charAt(i)
        if(char === currChar) count++
        else {
            encoding += count + currChar
            
            // сброс
            count = 1
            currChar = char
        }
    }
    
    encoding += count + currChar
    
    return encoding
}

Декодирование строки


Нам необходимо реализовать две вспомогательные функции:

1. Функцию, проверяющую является ли символ числом:

const isNumber = function(str) {
    return /^\d+$/.test(str)
}

2. Функцию, возвращающую количество символов до конца строки:

const addCountAmount = function(string, char, count) {
    for(let i = 1; i <= count; i++) {
        string += char
    }
    
    return string
}

Вот решение:

const decoding_string = function(string) {
    if(string.length === 0) return ''
    let currCount = 0
    let i = 0
    let decoding = ''
    
    while(i < string.length) {
        const char = string.charAt(i)
        if(isNumber(char)) {
            const num = +char
            currCount = currCount * 10 + num
        } else {
            decoding = addCountAmount(decoding, char, currCount)
            currCount = 0
        }
        
        i++
    }
    
    return decoding
}

Проверяем решение:

1. Строка "AAAABBBCCDAA" должна быть преобразована в "4A3B2C1D2A":

console.log(encoding_string("AAAABBBCCDAA")) // 4A3B2C1D2A

2. Обратное преобразование:

console.log(decoding_string("4A3B2C1D2A")) // AAAABBBCCDAA

Задача № 2


Есть лестница с N количеством ступеней. За один шаг можно подняться на одну или две ступени. Дано N. Напишите функцию, возвращающую количество уникальных способов подняться по лестнице. Порядок преодоления ступеней не важен.

Например, если N = 4, то существует 5 уникальных способов:

    1, 1, 1, 1
    2, 1, 1
    1, 2, 1
    1, 1, 2
    2, 2

Что если убрать ограничение на количество ступеней? Например, если X = {1, 3, 5}, мы можем подняться на 1, 3 или 5 ступеней за раз.

Решение


Функция, возвращающая количество уникальных способов подняться по лестнице (с ограничением):

const climb_stairs_1 = function(stairs) {
    if(stairs === 1) return 1
    if(stairs === 2) return 2

    let prev = 1
    let curr = 2
    for(let i = 2; i < stairs; i++) {
        const sum = prev + curr
        prev = curr
        curr = sum
    }
    return curr
}

Функция, возвращающая количество уникальных способов подняться по лестнице (без ограничения):

const climb_stairs_2 = function(stairs, nums) {
    const dp = Array(stairs + 1).fill(0)

    for(let i = 1; i <= stairs; i++) {
        // получаем общее количество f(i - x), где x - каждое число в nums
        let total = 0
        for(let j = 0; j < nums.length; j++) {
            const num = nums[j]

            // проверяем попадание в диапазон
            if(i - num > 0) total += dp[i - num]
        }
        dp[i] += total

        // если i имеется в nums, увеличиваем значение
        if(nums.indexOf(i) !== -1) dp[i] += 1
    }
    // получаем последнее число в dp
    return dp[dp.length - 1]
}

Проверяем решение:

console.log(climb_stairs_1(4)) // 5

console.log(climb_stairs_2(4, [1, 3, 5])) // 3

Задача № 3


Дано целое число K и строка S. Нужно найти длину самой длинной подстроки, содержащей не более K разных символов.

Например, дана s = "abcba" и k = 2. Самой длинной подстрокой с не более K разных символов является "bcb".

Решение


Вот мое решение:

const k_longest_substring = function(string, k) {
    let l = 0
    let r = 0
    const charCount = new Map()
    let longestSubstring = ''

    while(r < string.length) {
        const char = string.charAt(r)

        // обновляем счетчик
        if(charCount.has(char)) {
            charCount.set(char, charCount.get(char) + 1)
        } else {
            charCount.set(char, 1)
        }

        // размер charCount равен k
        // начинаем двигаться влево до тех пор, пока подстрока не будет содержать не более k разных символов
        if(charCount.size > k) {
            while(charCount.size > k && l < r) {
                const leftChar = string.charAt(l)
                const count = charCount.get(leftChar)

                if(count === 1) charCount.delete(leftChar)
                else charCount.set(leftChar, count - 1)

                l++
            }
        }

        const substring = string.substring(l, r + 1)
        longestSubstring = substring.length > longestSubstring.length ? substring : longestSubstring
        r++
    }
    return longestSubstring
}

Проверяем решение:

console.log(k_longest_substring("abcba", 2)) // bcb

Легко, не правда ли?

Благодарю за внимание.
Tags:
Hubs:
+7
Comments5

Articles