Advertisement
Kostiggig

Untitled

Aug 17th, 2024
885
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.48 KB | None | 0 0
  1. fun main() {
  2.     println(calculate(listOf(9), listOf(2))) // result=[1, 1]
  3.     println(calculate(listOf(9), listOf(1))) // result=[1, 0]
  4.     println(calculate(listOf(9), listOf(0))) // result=[0, 9] - лидирующий незначащий ноль можно удалить
  5.     println(calculate(listOf(9, 8), listOf(1))) // result=[9,9]
  6.     println(calculate(listOf(9, 9, 9), listOf(1))) // result=[1, 0, 0, 0]
  7.     println(calculate(listOf(9, 9, 8), listOf(1))) // result=[0, 9, 9, 9] - лидирующий незначащий ноль можно удалить
  8. }
  9.  
  10. // TC: max(O(a.size), O(b.size)) - временная сложность
  11. // SC: max(O(a.size), O(b.size) + 1) - сложность по памяти
  12. fun calculate(a: List<Int>, b: List<Int>): List<Int> {
  13.     // Добавляем 1 к максимальной длине числа, чтобы избавиться от граничащих случаев как a=[1], b=[9]
  14.     // Если не прибавлять 1, то result=[0-сумма 9 + 1], если добавить 1, то result=[1-то что мы запомнили при сложении 9 + 1, 0-сумма 9 + 1]
  15.     val res = ArrayList<Int>()
  16.     // заполняю результирующий массив нулями
  17.     repeat(max(a.size, b.size) + 1) {
  18.         res.add(0)
  19.     }
  20.  
  21.     // Нет необходимости разворачивать массивы и тратить дополнительную память на аллокацию новых
  22.  
  23.     // указатель(индекс) на текущую цифру в числе a
  24.     var i = a.size - 1
  25.  
  26.     // указатель(индекс) на текущую цифру в числе b
  27.     var j = b.size - 1
  28.  
  29.     // указатель(индекс) для записи результирующей суммы в res(result)
  30.     var k = res.size - 1
  31.     // то что запоминаем в уме, никогда не превышает 1, можно проверить на граничащих случаях 9 + 9 или 999 + 999
  32.     var save = 0
  33.     while (i >= 0 || j >= 0) {
  34.         // если указатель уходит за пределы массива, то дефолтное значение будет 0
  35.         // например a=[1], b=[6,7,8]
  36.         // на первой итерации i = 0(сылается на 1), j = 2(ссылатеся на 8)
  37.         // на второй итерации i = -1(не ссылается на элемент a, поэтому first = 0), j = 1(ссылается на 7)
  38.         val first = a.getOrElse(i) { 0 }
  39.         val second = b.getOrElse(j) { 0 }
  40.  
  41.         // sum гарантирована находится в диапазоне [0, 19], можно проверить на краевых случаях
  42.         // first=9, second=9, save=1 => sum = 9 + 9 + 1 = 19
  43.         val sum = first + second + save
  44.         // save(то что запоминаем в уме(еще называют carry) можно находить целочисленным делением на 10
  45.         // можно проверить на краевых случаях, так как sum находится в диапазоне [0, 19],то
  46.         // при sum=[0..9] save = 0, так как если (0 <= sum < 10), то деление числа < 10 на 10 дает нам ноль
  47.         // при sum=[10, 19] save = 0, так как если (10 <= sum <= 19), то деление на 10 дает нам 1
  48.         save = sum / 10
  49.  
  50.         // так как sum=[0..19], то последнее число можно получить остатком деления на 10
  51.         // если sum=[n = 0..9], то result=n % 10 = n
  52.         // если sum=[n = 10..19], то result = n % 10 = последней цифре sum, в случае 10=0, в случае 15=5, и так далее
  53.         val result = sum % 10
  54.         res[k] = result
  55.         i--
  56.         j--
  57.         k--
  58.     }
  59.     // случай, когда сложение двух чисел одинаковой длины может заполнить наш save, но мы выйдем из прошлого цикла
  60.     // Например, a=[9], b=[2], после первой итерации i=-1, j=-1 и мы выходим из цикла выше
  61.     // если не обработать этот кейс, то результат будет result=[0, 1], а ожидается [1,1]
  62.     if (save == 1){
  63.         res[0] = 1
  64.     }
  65.     return res
  66. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement