43. Multiply Strings - Explanation

Problem Link

Description

You are given two strings num1 and num2 that represent non-negative integers.

Return the product of num1 and num2 in the form of a string.

Assume that neither num1 nor num2 contain any leading zero, unless they are the number 0 itself.

Note: You can not use any built-in library to convert the inputs directly into integers.

Example 1:

Input: num1 = "3", num2 = "4"

Output: "12"

Example 2:

Input: num1 = "111", num2 = "222"

Output: "24642"

Constraints:

  • 1 <= num1.length, num2.length <= 200
  • num1 and num2 consist of digits only.


Topics

Recommended Time & Space Complexity

You should aim for a solution with O(m*n) time and O(m+n) space, where m is the length of the string num1 and n is the length of the string num2.


Hint 1

Implement a helper function that takes two number strings and returns their sum. Ensure that the length of num1 is greater than num2, swapping them if necessary. Can you think of a way to multiply the strings? Maybe you should first consider basic multiplication, where num1 is multiplied by each digit of num2.


Hint 2

When multiplying num1 with each digit of num2, we iterate through num2 in reverse order. Based on the digit's position, we pad zeros to the multiplication result accordingly—no padding for the last digit, one zero for the second last, and so on. What should be the next step after each multiplication? Maybe you should implement a helper function to handle this.


Hint 3

We implement a helper function that takes num1, a digit, and a variable zeroes, returning the multiplication result with zeroes padded at the end. A global string res stores the final result.


Hint 4

In the main function, we iterate through num2 in reverse order, calling the helper function to multiply num1 with the current digit and append the appropriate number of padding zeros. We then call another helper function that takes this multiplication result and the global result string res, adds them, and updates res.


Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • String Manipulation - Converting characters to digits and building result strings
  • Grade-School Multiplication - Understanding how manual digit-by-digit multiplication works with carry propagation
  • Arrays - Using arrays to accumulate partial products at specific positions

1. Multiplication & Addition

Intuition

This approach mimics how we multiply numbers by hand. We multiply the larger number by each digit of the smaller number (starting from the rightmost digit), shifting the result appropriately by appending zeros. Then we add all these partial products together. This simulates the grade-school multiplication algorithm but operates entirely on strings to handle arbitrarily large numbers.

Algorithm

  1. If either number is "0", return "0" immediately.
  2. Ensure num1 is the longer number (swap if needed for efficiency).
  3. For each digit in num2 from right to left:
    • Multiply num1 by that single digit using a helper function.
    • Append the appropriate number of trailing zeros based on the digit's position.
    • Add this partial res to the running total using a string addition helper.
  4. The string addition and multiplication helpers handle carry values and build the result digit by digit.
  5. Return the accumulated res.
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        if num1 == "0" or num2 == "0":
            return "0"

        if len(num1) < len(num2):
            return self.multiply(num2, num1)

        res, zero = "", 0
        for i in range(len(num2) - 1, -1, -1):
            cur = self.mul(num1, num2[i], zero)
            res = self.add(res, cur)
            zero += 1

        return res

    def mul(self, s: str, d: str, zero: int) -> str:
        i, carry = len(s) - 1, 0
        d = int(d)
        cur = []

        while i >= 0 or carry:
            n = int(s[i]) if i >= 0 else 0
            prod = n * d + carry
            cur.append(str(prod % 10))
            carry = prod // 10
            i -= 1

        return ''.join(cur[::-1]) + '0' * zero

    def add(self, num1: str, num2: str) -> str:
        i, j, carry = len(num1) - 1, len(num2) - 1, 0
        res = []

        while i >= 0 or j >= 0 or carry:
            n1 = int(num1[i]) if i >= 0 else 0
            n2 = int(num2[j]) if j >= 0 else 0
            total = n1 + n2 + carry
            res.append(str(total % 10))
            carry = total // 10
            i -= 1
            j -= 1

        return ''.join(res[::-1])

Time & Space Complexity

  • Time complexity: O(min(m,n)(m+n))O(min(m, n) * (m + n))
  • Space complexity: O(m+n)O(m + n)

Where mm is the length of the string num1num1 and nn is the length of the string num2num2.


2. Multiplication

Intuition

Instead of generating partial products and adding them as separate strings, we can use a single result array to accumulate all digit multiplications in place. When we multiply digit i of num1 by digit j of num2, the result contributes to position i + j in the final answer. By reversing both strings first, we can work with indices that naturally align with place values. After processing all digit pairs, we handle carries and convert the result array back to a string.

Algorithm

  1. If either number is "0", return "0" immediately.
  2. Create a result array of size len(num1) + len(num2) initialized to zeros.
  3. Reverse both input strings so index 0 corresponds to the ones place.
  4. For each pair of indices (i1, i2):
    • Multiply the corresponding digits.
    • Add the product to res[i1 + i2].
    • Propagate any carry to res[i1 + i2 + 1].
    • Keep only the ones digit at res[i1 + i2].
  5. Reverse the res array, skip leading zeros, and join the digits into a string.
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        if "0" in [num1, num2]:
            return "0"

        res = [0] * (len(num1) + len(num2))
        num1, num2 = num1[::-1], num2[::-1]
        for i1 in range(len(num1)):
            for i2 in range(len(num2)):
                digit = int(num1[i1]) * int(num2[i2])
                res[i1 + i2] += digit
                res[i1 + i2 + 1] += res[i1 + i2] // 10
                res[i1 + i2] = res[i1 + i2] % 10

        res, beg = res[::-1], 0
        while beg < len(res) and res[beg] == 0:
            beg += 1
        res = map(str, res[beg:])
        return "".join(res)

Time & Space Complexity

  • Time complexity: O(mn)O(m * n)
  • Space complexity: O(m+n)O(m + n)

Where mm is the length of the string num1num1 and nn is the length of the string num2num2.

Common Pitfalls

Not Handling the Zero Case

When either input is "0", the result must be "0". Failing to check this upfront can lead to returning an empty string or a string with leading zeros. Always check for zero inputs before proceeding with multiplication to avoid unnecessary computation and incorrect output formatting.

Incorrect Position Indexing for Digit Products

When multiplying digit i of num1 by digit j of num2, the result contributes to a specific position in the output array. If strings are reversed, the position is i + j; if not, careful index calculation is needed. Off-by-one errors in position calculation cause digits to be placed incorrectly, resulting in a wrong final product.

Forgetting to Handle Leading Zeros in the Result

After populating the result array, there may be leading zeros (especially at the highest index positions after reversing). Skipping these zeros before converting to a string is essential. However, if all digits are zero (which should not happen if the zero case is handled), ensure at least one "0" is returned rather than an empty string.