Задача №1: сложение массивов
Мы хотим складывать очень большие числа, которые превышают емкость базовых типов, поэтому мы храним их в виде массива неотрицательных чисел.
Нужно написать функцию, которая примет на вход два таких массива, вычислит сумму чисел, представленных массивами, и вернет результат в виде такого же массива.
Пример
ввод
arr1 = [1, 2, 3] # число 123
arr2 = [4, 5, 6] # число 456
вывод
res = [5, 7, 9] # число 579 (допустим ответ с первым незначимым нулем [0, 5, 7, 9])
Решение
<?php /** * Calc arrays sum * @param array $a * @param array $b * @return array */ function calcSum(array $a, array $b): array { $res = []; $ost = 0; while (count($a) > 0 || count($b) > 0) { if (count($a)) { $digitA = array_pop($a); } else { $digitA = 0; } if (count($b)) { $digitB = array_pop($b); } else { $digitB = 0; } $sum = $digitA + $digitB + $ost; $digit = $sum % 10; $res[] = $digit; $ost = floor($sum / 10); } if ($ost > 0) { $res[] = $ost; } $res = array_reverse($res); // 71 ==> 17 return $res; } ///////////////////////////////////////// $a = [1]; # число 1 $b = [2]; # число 2 $res = calcSum($a, $b); var_dump($res); // [3] # число 3 echo "n"; $a = [1, 2, 3]; # число 123 $b = [4, 5, 6]; # число 456 $res = calcSum($a, $b); var_dump($res); // [5, 7, 9] # число 579 (допустим ответ с первым незначимым нулем [0, 5, 7, 9]) echo "n"; $a = [2, 9, 2, 3]; # число 2923 $b = [7, 5, 6]; # число 756 $res = calcSum($a, $b); var_dump($res); // [3, 6, 7, 9] # число 3679
Оценка сложности:
-
алгоритм — О(n)
-
по памяти О(n)
Задача №2: самые популярные элементы массива
Дан массив целых чисел nums и целое число k.
Нужно написать функцию на PHP, которая вынимает из массива k наиболее часто встречающихся элементов.
Пример
ввод
nums = [1,1,1,2,2,3]
k = 2
вывод (в любом порядке)
[1, 2]
Решение #1 (рабочее, но не оптимальное)
Вот функция на PHP для выбора k наиболее часто встречающихся элементов из массива:
<?php /** * AvitoTech task #2: Frequent numbers * (not optimal solution, see optimal in freq_nums2.php) * * Дан массив целых чисел nums и целое число k. * Нужно написать функцию на PHP, которая вынимает из массива k наиболее часто встречающихся элементов. */ function topKFrequent222($nums, $k) { $freq = []; foreach ($nums as $num) { $freq[$num] = isset($freq[$num]) ? $freq[$num] + 1 : 1; } arsort($freq); $result = array_slice(array_keys($freq), 0, $k); return $result; } /** * Get frequent numbers * @param array $arr * @param int $limit * @return array */ function getMaxFreqNums(array $arr, int $limit): array { $freqArr = []; foreach ($arr as $num) { if (isset($freqArr[$num])) { $freqArr[$num] += 1; } else { $freqArr[$num] = 1; } } arsort($freqArr); $res = array_slice(array_keys($freqArr), 0, $limit); return $res; } var_dump(getMaxFreqNums([1,1,1,2,2,3,3,3,3,3], 2)); // [3, 1]
Как это работает:
-
Подсчитываем частоту каждого элемента в массиве
-
Сортируем массив частот по убыванию
-
Берем первые k ключи (элементы) из отсортированного массива
Это решение не оптимально, т.к. алг. сложность — O(Nlog(n)) из-за функции сортировки:
Функция arsort в PHP сортирует массив по значению в обратном порядке (от большего к меньшему). Алгоритмическая сложность функции arsort: O(N log N), где N — размер сортируемого массива.
Как решить задачу со временем O(N)? Смотрим решение №2.
Решение #2 (оптимизированное)
Здесь вместо сортировки строим хеш-массив вида:
[<частота> => <элементы>]
Т.о., пробегаясь по его элементам (от старшего элемента вниз), получим элементы исходного массива с максимальными частотами.
<?php /** * AvitoTech task #2: Frequent numbers * (optimized solution) * * Дан массив целых чисел nums и целое число k. * Нужно написать функцию на PHP, которая вынимает из массива k наиболее часто встречающихся элементов. */ /** * Get frequent numbers * @param array $freqs * @param int $limit * @return array */ function getMaxFreqNums(array $freqs, int $limit): array { $freqArr = []; if(!is_array($freqs) || !count($freqs)) { return []; } // [num => frequence] foreach ($freqs as $num) { if (isset($freqArr[$num])) { // [1 => 3, 2 => 2, 3 => 4, 4 => 4, 1 => 5] $freqArr[$num] += 1; } else { $freqArr[$num] = 1; } } // [frequence => <nums_array>] $tmpArr = []; foreach ($freqArr as $num => $freq) { $tmpArr[$freq][] = $num; // [1 => [5], 2 => [2], 3 => [1], 4 => [3, 4]] } $freqArr = $tmpArr; // count result as slice of $maxArr $res = []; $freqArrKeys = array_keys($freqArr); $maxKey = max($freqArrKeys); for ($i = $maxKey; $i >= 0; $i--) { $freqs = (isset($freqArr[$i]) ? $freqArr[$i] : []); foreach ($freqs as $elem) { $res[] = $elem; if (count($res) >= $limit) { return $res; } } } return $res; } //////////////////////////////////// echo "n"; var_dump(getMaxFreqNums([], 2)); // [] echo "n"; var_dump(getMaxFreqNums([1], 1)); // [1] echo "n"; var_dump(getMaxFreqNums([1,1,1,2,2,3,3,3,3,3,3,4,4,4,4,4,5], 2)); // [3, 4]
Нет Ответов