
Доброго времени суток. Представляю вашему вниманию перевод статьи «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
Легко, не правда ли?
Благодарю за внимание.
