LeetCode 537 - Complex Number Multiplication
This problem asks us to multiply two complex numbers represented as strings and return the result in the same string format.
Difficulty: 🟡 Medium
Topics: Math, String, Simulation
Solution
Problem Understanding
This problem asks us to multiply two complex numbers represented as strings and return the result in the same string format.
A complex number is written as:
"real+imaginaryi"
For example:
"1+1i"represents $1 + i$"1+-1i"represents $1 - i$
The input strings always follow a valid format, meaning we do not need to worry about malformed input. Each number contains:
- A real part, which is an integer
- An imaginary part, which is also an integer
- The imaginary unit
i, where:
$$i^2 = -1$$
The task is to parse both input strings, multiply the complex numbers mathematically, and return the result in exactly the same format.
If we denote:
$$(a + bi)$$
and
$$(c + di)$$
their multiplication becomes:
$$(a + bi)(c + di)$$
Expanding this expression:
$$= ac + adi + bci + bd i^2$$
Since:
$$i^2 = -1$$
we get:
$$= (ac - bd) + (ad + bc)i$$
So the final result consists of:
- Real part:
ac - bd - Imaginary part:
ad + bc
The constraints are small, since both real and imaginary values lie within [-100, 100]. This means performance is not a concern here. The challenge is primarily about correctly parsing the string representation and implementing the multiplication formula without mistakes.
An important observation is that inputs such as "1+-1i" contain a negative imaginary part. A naive parser that simply splits on '+' carelessly may fail if it does not correctly handle negative numbers.
The problem guarantees that all inputs are valid complex numbers, so we do not need defensive validation logic.
Important Edge Cases
A few cases can easily trip up an implementation:
- Negative imaginary values, such as
"1+-1i", because the imaginary component contains a minus sign. - Zero values, such as
"0+0i"or"0+1i", which can produce zero in either component. - Negative real values, such as
"-1+2i", which must still parse correctly. - Results with negative values, where the output format must remain
"real+imaginaryi", even if the imaginary part is negative, for example"0+-2i".
Approaches
Brute Force Approach
A brute force interpretation would be to simulate the multiplication by manually expanding the algebraic expression character by character, treating the string as a mathematical expression and evaluating every term separately.
For example:
(1 + i)(1 + i)
would expand into:
1 * 1
1 * i
i * 1
i * i
Then we would simplify the result using:
$$i^2 = -1$$
While this approach is mathematically correct, it introduces unnecessary complexity. We would need to tokenize the string, simulate symbolic multiplication, track real and imaginary components separately, and simplify terms afterward.
Given that complex multiplication has a direct formula, symbolic expansion is overkill.
Key Insight
The important observation is that every valid complex number always has exactly two integer components:
$$a + bi$$
If we can extract a and b from the string, multiplication becomes straightforward:
$$(a + bi)(c + di) = (ac - bd) + (ad + bc)i$$
Instead of simulating algebra symbolically, we only need to:
- Parse the real and imaginary parts.
- Apply the multiplication formula.
- Format the result back into a string.
This makes the solution both simple and efficient.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(n) | Simulates symbolic multiplication and simplification |
| Optimal | O(n) | O(1) | Parse integers and apply the complex multiplication formula |
Here, n represents the length of the input strings. Since the strings are tiny and bounded, the runtime is effectively constant.
Algorithm Walkthrough
Optimal Algorithm
- Parse the first complex number
Split the string on '+' to separate the real and imaginary components. Remove the trailing 'i' from the imaginary part and convert both values to integers.
2. Parse the second complex number
Repeat the same parsing logic for the second input string. 3. Apply the multiplication formula
Suppose the parsed values are:
$$(a + bi)$$
and
$$(c + di)$$
Compute:
- Real part:
$$ac - bd$$
- Imaginary part:
$$ad + bc$$ 4. Format the result string
Construct the output exactly as required:
"real+imaginaryi"
Even if the imaginary part is negative, the format remains unchanged, for example:
"0+-2i"
Why it works
The correctness comes directly from the algebraic definition of complex number multiplication:
$$(a + bi)(c + di) = ac + adi + bci + bd i^2$$
Since:
$$i^2 = -1$$
this simplifies to:
$$(ac - bd) + (ad + bc)i$$
The algorithm parses the components correctly and computes exactly these two values, guaranteeing the correct result.
Python Solution
class Solution:
def complexNumberMultiply(self, num1: str, num2: str) -> str:
def parse_complex(number: str) -> tuple[int, int]:
real_part, imaginary_part = number.split("+")
return int(real_part), int(imaginary_part[:-1])
real1, imaginary1 = parse_complex(num1)
real2, imaginary2 = parse_complex(num2)
real_result = (
real1 * real2
- imaginary1 * imaginary2
)
imaginary_result = (
real1 * imaginary2
+ imaginary1 * real2
)
return f"{real_result}+{imaginary_result}i"
Implementation Explanation
The solution starts by defining a helper function called parse_complex. This function converts a complex number string into its numerical components.
We split the string on '+', which separates the real and imaginary sections. Since the imaginary portion ends with 'i', we remove the final character using slicing:
imaginary_part[:-1]
Both pieces are converted into integers.
After parsing both inputs, we compute the multiplication result using the standard complex multiplication formula:
real1 * real2 - imaginary1 * imaginary2
for the real component, and:
real1 * imaginary2 + imaginary1 * real2
for the imaginary component.
Finally, we return the result using Python string formatting to match the required LeetCode output format exactly.
Go Solution
package main
import (
"fmt"
"strconv"
"strings"
)
func complexNumberMultiply(num1 string, num2 string) string {
parseComplex := func(number string) (int, int) {
parts := strings.Split(number, "+")
realPart, _ := strconv.Atoi(parts[0])
imaginaryStr := strings.TrimSuffix(parts[1], "i")
imaginaryPart, _ := strconv.Atoi(imaginaryStr)
return realPart, imaginaryPart
}
real1, imaginary1 := parseComplex(num1)
real2, imaginary2 := parseComplex(num2)
realResult := real1*real2 - imaginary1*imaginary2
imaginaryResult := real1*imaginary2 + imaginary1*real2
return fmt.Sprintf("%d+%di", realResult, imaginaryResult)
}
Go Specific Notes
The Go implementation follows the same logic as Python, but string parsing requires standard library helpers.
We use:
strings.Split()to separate real and imaginary parts.strings.TrimSuffix()to remove the trailing'i'.strconv.Atoi()to convert strings into integers.
Error handling from Atoi is ignored because the problem guarantees valid input.
Unlike Python f-strings, Go uses:
fmt.Sprintf()
to build the final result string.
Integer overflow is not a concern here because values remain very small. The largest multiplication is well within Go's int range.
Worked Examples
Example 1
Input
num1 = "1+1i"
num2 = "1+1i"
Parsing Phase
| Variable | Value |
|---|---|
| real1 | 1 |
| imaginary1 | 1 |
| real2 | 1 |
| imaginary2 | 1 |
Multiplication Phase
Real component:
$$(1 \times 1) - (1 \times 1)$$
$$1 - 1 = 0$$
Imaginary component:
$$(1 \times 1) + (1 \times 1)$$
$$1 + 1 = 2$$
Final Result
"0+2i"
Example 2
Input
num1 = "1+-1i"
num2 = "1+-1i"
Parsing Phase
| Variable | Value |
|---|---|
| real1 | 1 |
| imaginary1 | -1 |
| real2 | 1 |
| imaginary2 | -1 |
Multiplication Phase
Real component:
$$(1 \times 1) - (-1 \times -1)$$
$$1 - 1 = 0$$
Imaginary component:
$$(1 \times -1) + (-1 \times 1)$$
$$-1 + (-1) = -2$$
Final Result
"0+-2i"
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Parsing the strings requires traversing their characters once |
| Space | O(1) | Only a fixed number of variables are used |
Although the input size is tiny and bounded, formally the algorithm runs in linear time relative to the string length because parsing scans the input characters. Space complexity is constant since we only store a handful of integers and temporary strings.
Test Cases
solution = Solution()
assert solution.complexNumberMultiply(
"1+1i", "1+1i"
) == "0+2i" # provided example
assert solution.complexNumberMultiply(
"1+-1i", "1+-1i"
) == "0+-2i" # provided negative imaginary example
assert solution.complexNumberMultiply(
"0+0i", "0+0i"
) == "0+0i" # zero multiplication
assert solution.complexNumberMultiply(
"0+1i", "0+1i"
) == "-1+0i" # i^2 = -1
assert solution.complexNumberMultiply(
"-1+1i", "1+1i"
) == "-2+0i" # negative real component
assert solution.complexNumberMultiply(
"-1+-1i", "-1+-1i"
) == "0+2i" # both parts negative
assert solution.complexNumberMultiply(
"100+100i", "100+100i"
) == "0+20000i" # upper boundary values
assert solution.complexNumberMultiply(
"-100+-100i", "100+100i"
) == "0+-20000i" # mixed boundaries
| Test | Why |
|---|---|
"1+1i", "1+1i" |
Validates the basic multiplication example |
"1+-1i", "1+-1i" |
Ensures negative imaginary parsing works |
"0+0i", "0+0i" |
Tests zero handling |
"0+1i", "0+1i" |
Verifies correct handling of i² = -1 |
"-1+1i", "1+1i" |
Tests negative real values |
"-1+-1i", "-1+-1i" |
Ensures double negatives parse correctly |
"100+100i", "100+100i" |
Tests upper constraint boundary |
"-100+-100i", "100+100i" |
Tests mixed sign boundary values |
Edge Cases
Negative Imaginary Part
Inputs such as:
"1+-1i"
can cause bugs if parsing is done incorrectly. A naive parser might misinterpret the minus sign or split improperly. This implementation safely splits only on '+' and then converts the resulting substring directly into an integer, preserving negative signs correctly.
Multiplication Result Equals Zero
Some products eliminate either the real or imaginary component entirely. For example:
"1+1i" * "1+1i"
produces:
"0+2i"
The implementation explicitly computes both components independently, so zero values are naturally preserved without requiring special handling.
Pure Imaginary Cancellation
Cases where the imaginary terms cancel out can produce results such as:
"-2+0i"
This is important because the output format still requires the imaginary component to appear. The implementation always returns:
"real+imaginaryi"
ensuring the result remains valid even when one component becomes zero.