Multiply Strings

Difficulty: Medium

You're given two non-negative numbers, each written out as a string of digits (they can be far too large to fit in a normal numeric type). Multiply them and return the product, also as a string of digits.

You can't just convert the strings to numbers and multiply directly - the whole point is that these numbers may be too big for that to work correctly.

Examples

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

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

123 * 456 = 56088, computed digit by digit without ever converting the full strings to numbers.

Input: num1 = "0", num2 = "12"
Output: "0"

Constraints

  • 1 <= num1.length, num2.length <= 200

  • num1 and num2 consist of digits only.

  • Neither num1 nor num2 has leading zeros, except num1 and num2 themselves being exactly "0".

Approach

This is the grade-school multiplication algorithm, just done on digit strings instead of numbers you already know how to multiply directly. One way to do it: multiply the first number by a single digit of the second number at a time, right to left, padding each of those partial products with the right number of trailing zeros for its place value, and add every partial product into a running total using ordinary string addition. It's correct, but each of those additions redoes work across digits that were already settled by earlier additions.

A more direct approach skips the repeated string additions entirely. Multiplying digit num1[i] by digit num2[j] always contributes to exactly two positions of the final answer (its own digit, plus a possible carry into the position to its left) - based only on i + j. Accumulating every digit-pair's contribution straight into a results array, indexed by position, produces the entire answer in a single pass, with only one conversion back to a string at the very end.

Solutions

Brute Force - Digit-by-Digit With String Addition

For each digit of num2 (right to left), multiply it against the entire num1 to get a partial product, pad it with trailing zeros for its place value, and add it into a running total using ordinary string addition.

function multiply(num1, num2) {
  if (num1 === "0" || num2 === "0") return "0";

  let result = "0";

  for (let i = num2.length - 1; i >= 0; i--) {
    const digit = Number(num2[i]);
    let carry = 0;
    let partial = "";

    for (let j = num1.length - 1; j >= 0; j--) {
      const product = Number(num1[j]) * digit + carry;
      partial = (product % 10) + partial;
      carry = Math.floor(product / 10);
    }
    if (carry > 0) partial = carry + partial;

    // Shift this partial product left by its place value
    partial += "0".repeat(num2.length - 1 - i);

    result = addStrings(result, partial);
  }

  return result;
}

function addStrings(a, b) {
  let result = "";
  let carry = 0;
  let i = a.length - 1;
  let j = b.length - 1;

  while (i >= 0 || j >= 0 || carry > 0) {
    const digitA = i >= 0 ? Number(a[i]) : 0;
    const digitB = j >= 0 ? Number(b[j]) : 0;
    const sum = digitA + digitB + carry;
    result = (sum % 10) + result;
    carry = Math.floor(sum / 10);
    i--;
    j--;
  }

  return result;
}

Time: O(m · n · max(m, n)) - m·n for the digit multiplications, plus a string addition of length up to m+n after each of the n digits · Space: O(m + n)

Optimal - Accumulate Into a Positions Array

Multiplying num1[i] by num2[j] always lands on positions i+j (its carry) and i+j+1 (its ones digit) of the final answer, regardless of the other digits. Accumulate every digit pair's product directly into a results array at those two positions, then read the array off as the final digit string.

function multiply(num1, num2) {
  if (num1 === "0" || num2 === "0") return "0";

  const m = num1.length, n = num2.length;
  const digits = new Array(m + n).fill(0);

  for (let i = m - 1; i >= 0; i--) {
    for (let j = n - 1; j >= 0; j--) {
      const product = Number(num1[i]) * Number(num2[j]);
      const sumPos = i + j + 1; // ones place of this product
      const carryPos = i + j;   // tens place of this product

      const total = digits[sumPos] + product;
      digits[sumPos] = total % 10;
      digits[carryPos] += Math.floor(total / 10);
    }
  }

  // Skip a single leading zero, if the result didn't need the full width
  let start = 0;
  while (start < digits.length - 1 && digits[start] === 0) {
    start++;
  }

  return digits.slice(start).join("");
}

Time: O(m · n) · Space: O(m + n)