Постановка задачи

Даны два неотрицательных целых числа num1 и num2, представленные в виде строк, вернуть произведение num1 и num2, а также представлен в виде строки.

Примечание. Вы не должны использовать какие-либо встроенные библиотеки BigInteger или напрямую преобразовывать входные данные в целые числа.

Постановка задачи взята с: https://leetcode.com/problems/multiply-strings.

Пример 1:

Input: num1 = "2", num2 = "3"
Output: "6"

Пример 2:

Input: num1 = "123", num2 = "456"
Output: "56088"

Ограничения:

- 1 <= num1.length, num2.length <= 200
- num1 and num2 consist of digits only.
- Both num1 and num2 do not contain any leading zero, except the number 0 itself.

Объяснение

Использование стандартного элементарного математического подхода

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

Проверим алгоритм:

- set m = num1.size() and n = num2.size()
  // create a string of length m + n with all chars as '0'  
  set result = string(m + n, '0') 
  set indexCounter = 0
  initialize index, carry, currentNumber, sum
- loop for i = m - 1; i >= 0; i--
  - set carry = 0
  - set index = m + n - 1 - indexCounter
  - set currentNumber = num1[i] - '0'
  - loop for j = n - 1; j >= 0; j--
    - set sum = (num2[j] - '0') * currentNumber + carry + result[index] - '0'
    - update carry = sum / 10
    - set result[index] = (char)(sum % 10 + '0')
    - update index = index - 1
  - loop while carry > 0
    - set sum = result[index] - '0' + carry
    - update carry = sum / 10
    - set result[index] = (char)(sum % 10 + '0')
    - update index = index - 1
  - update indexCounter = indexCounter + 1
- set lastZeroIndex = 0
- loop while lastZeroIndex < m + n && result[lastZeroIndex] == '0'
  - lastZeroIndex++
- if lastZeroIndex == m + n
  - return "0"
- return string(result.begin() + lastZeroIndex, result.end())

С++ решение

class Solution {
public:
    string multiply(string num1, string num2) {
        int m = num1.size();
        int n = num2.size();
        string result(m + n, '0');
        int indexCounter = 0;
        int index, carry, currentNumber, sum;
        for(int i = m - 1; i >= 0; i--){
            carry = 0;
            index = m + n - 1 - indexCounter;
            currentNumber = num1[i] - '0';
            for(int j = n - 1; j >= 0; j--){
                sum = (num2[j] - '0')*currentNumber + carry + result[index] - '0';
                carry = sum / 10;
                result[index] = (char)(sum % 10 + '0');
                index--;
            }
            while(carry > 0){
                sum = result[index] - '0' + carry;
                carry = sum / 10;
                result[index] = (char)(sum % 10 + '0');
                index--;
            }
            indexCounter++;
        }
        int lastZeroIndex = 0;
        while(lastZeroIndex < m + n && result[lastZeroIndex] == '0'){
            lastZeroIndex++;
        }
        if(lastZeroIndex == m + n){
            return "0";
        }
        return string(result.begin() + lastZeroIndex, result.end());
    }
};

Голанг решение

import "strings"
func multiply(num1 string, num2 string) string {
    m, n := len(num1), len(num2)
    result := make([]byte, m + n)
    carry, indexCounter, sum, index := 0, 0, 0, 0
    for i := m - 1; i >= 0; i-- {
        carry = 0
        currentNumber := int(num1[i] - '0')
        index = m + n - 1 - indexCounter
        for j := n - 1; j >= 0; j-- {
            sum = int(num2[j] - '0') * currentNumber + carry + int(result[index])
            carry = sum / 10
            result[index] = byte(sum % 10)
            index--
        }
        for carry > 0 {
            sum = int(result[index]) + carry
            carry = sum / 10
            result[index] = byte(sum % 10)
            index--
        }
        indexCounter++
    }
    lastZeroIndex := 0
    for lastZeroIndex < m + n && result[lastZeroIndex] == 0 {
        lastZeroIndex++
    }
    if lastZeroIndex == m + n {
        return "0"
    }
    return string(result[lastZeroIndex:])
}

Javascript-решение

var multiply = function(num1, num2) {
    let m = num1.length, n = num2.length;
    let result = [];
    let carry, currentNumber, index, sum;
    let indexCounter = 0;
    for(let i = m - 1; i >= 0; i--){
        carry = 0;
        currentNumber = num1[i] - '0';
        index = m + n - 1 - indexCounter;
        for(let j = n - 1; j >= 0; j--){
            sum = (num2[j] - '0') * currentNumber + carry + (result[index] ? result[index] : 0);
            carry = Math.floor(sum / 10);
            result[index] = sum % 10;
            index--;
        }
        while(carry > 0){
            sum = (result[index] ? result[index] : 0) + carry;
            carry = Math.floor(sum / 10);
            result[index] = sum % 10;
            index--;
        }
        indexCounter++;
    }
    let lastZeroIndex = 0;
    for(;lastZeroIndex < m + n && result[lastZeroIndex] == 0;){
        lastZeroIndex++
    }
    if(lastZeroIndex == m + n){
        return "0";
    }
    return result.join("").replace(/^0+/, '')
};

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

Input: num1 = "23", num2 = "46"
Step 1: m = num1.size()
          = 2
        n = num2.size()
          = 2
        string result(m + n, '0')
        result = "0000"
        indexCounter = 0
        int index, carry, currentNumber, sum
Step 2: loop for i = m - 1; i >= 0
        i = 2 - 1
          = 1
        i >= 0
        1 >= 0
        true
        carry = 0
        index = m + n - 1 - indexCounter
              = 2 + 2 - 1 - 0
              = 3
        currentNumber = num1[i] - '0'
                      = num1[1] - '0'
                      = '3' - '0'
                      = 3
        loop for j = n - 1; j >= 0
        j = n - 1
          = 2 - 1
          = 1
          sum = (num2[j] - '0')*currentNumber + carry + result[index] - '0'
              = (num2[1] - '0') * 3 + 0 + result[3] - '0'
              = ('6' - '0') * 3 + 0 + '0' - '0'
              = 6*3 + 0 + 0
              = 18
          carry = sum / 10
                = 18/ 10
                = 1
          result[3] = (char)(sum % 10 + '0')
                        = (char)(18 % 10 + '0')
                        = (char)(8 + '0')
                        = '8'
          index--
          index = index - 1
                = 3 - 1
                = 2
          j--
          j = 0
        loop for j >= 0
        0 >= 0
        true
          sum = (num2[j] - '0')*currentNumber + carry + result[index] - '0'
              = (num2[0] - '0') * 3 + 1 + result[2] - '0'
              = ('4' - '0') * 3 + 1 + '0' - '0'
              = 4*3 + 1 + 0
              = 13
          carry = sum / 10
                = 13 / 10
                = 1
          result[2] = (char)(sum % 10 + '0')
                        = (char)(13 % 10 + '0')
                        = (char)(3 + '0')
                        = '3'
          index--
          index = index - 1
                = 2 - 1
                = 1
          j--
          j = -1
        loop for j >= 0
        -1 >= 0
        false
        loop while carry > 0
        1 > 0
        true
          sum = result[index] - '0' + carry
              = result[1] - '0' + 1
              = '0' - '0' + 1
              = 1
          carry = sum / 10
                = 1 / 10
                = 0
          result[1] = (char)(sum % 10 + '0')
                    = (char)(1 % 10 + '0')
                    = (char)(1 + '0')
                    = '1'
          index--
          index = index - 1
                = 1 - 1
                = 0
        indexCounter++
        indexCounter = indexCounter + 1
                     = 1
        i--
        i = i - 1
          = 1 - 1
          = 0
        result = ['0', '1', '3', '8']
Step 3: loop for i >= 0
        0 >= 0
        true
        carry = 0
        index = m + n - 1 - indexCounter
              = 2 + 2 - 1 - 1
              = 2
        currentNumber = num1[i] - '0'
                      = num1[0] - '0'
                      = '2' - '0'
                      = 2
        loop for j = n - 1; j >= 0
        j = n - 1
          = 2 - 1
          = 1
        sum = (num2[j] - '0')*currentNumber + carry + result[index] - '0'
            = (num2[1] - '0') * 2 + 0 + result[2] - '0'
            = ('6' - '0') * 2 + 0 + '3' - '0'
            = 6 * 2 + 3
            = 15
        carry = sum / 10
              = 15 / 10
              = 1
        result[2] = (char)(sum % 10 + '0')
                  = (char)(15 % 10 + '0')
                  = (char)(5 + '0')
                  = '5'
        index--
        index = index - 1
              = 2 - 1
              = 1
        j--
        j = j - 1
          = 1 - 1
          = 0
        loop for j >= 0
        0 >= 0
        true
        sum = (num2[j] - '0') * currentNumber + carry + result[index] - '0'
            = ('4' - '0') * 2 + 1 + result[1] - '0'
            = 4 * 2 + 1 + '1' - '0'
            = 8 + 1 + 1
            = 10
        carry = sum / 10
              = 10 / 10
              = 1
        result[1] = (char)(sum % 10 + '0')
                  = (char)(10 % 10 + '0')
                  = (char)(0 + '0')
                  = '0'
        index--
        index = index - 1
              = 1 - 1
              = 0
        j--
        j = j - 1
          = 0 - 1
          = -1
        loop for j >= 0
        -1 >= 0
        false
        loop while carry > 0
        1 > 0
        true
          sum = result[index] - '0' + carry
              = result[0] - '0' + 1
              = '0' - '0' + 1
              = 1
          carry = sum / 10
                = 1 / 10
                = 0
          result[0] = (char)(sum % 10 + '0')
                    = (char)(1 % 10 + '0')
                    = (char)(1 + '0')
                    = '1'
          index--
          index = index - 1
                = 0 - 1
                = -1
        loop while carry > 0
        0 > 0
        false
        indexCounter++
        indexCounter = indexCounter + 1
                     = 2
        i--
        i = i - 1
          = 0 - 1
          = -1
        result = ['1', '0', '5', '8']
Step 4: loop for i >= 0
        -1 >= 0
        false
Step 5: lastZeroIndex = 0
Step 6: loop while lastZeroIndex < m + n && result[lastZeroIndex] == '0'
          0 < 2 + 2 && result[0] == '0'
          0 < 4 && '1' == '0'
          true && false
          false
Step 7: if lastZeroIndex == m + n
          0 == 2 + 2
          0 == 4
          false
Step 8: return string(result.begin() + lastZeroIndex, result.end())
          string(result.begin() + 0, result.end())
          string(['1', '0', '5', '8'])
          "1058"
So we return the result as "1058".

Первоначально опубликовано на https://alkeshghorpade.me.