Problem#
Given two non-negative integers num1
and num2
represented as strings, return the product of num1
and num2
, also represented as a string.
Note: You must not use any built-in BigInteger library or convert the inputs to integer directly.
### Examples#
Example 1#
1
2
Input: num1 = "2" , num2 = "3"
Output: "6"
Example 2#
1
2
Input: num1 = "123" , num2 = "456"
Output: "56088"
Constraints#
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.
Solution#
First read about - Multiplication of Two Numbers .
The key to solve this problem is multiplying each digit of the numbers from the right to left at the corresponding positions and get the sum values at each position. That is how we do multiplication manually.
Method 1 – Right to Left Multiplication (No Reversing)#
Intuition#
Since the numbers are large, we cannot use normal integer multiplication. Instead, we use the manual multiplication method: multiply each digit from right to left and sum the results at the correct positions, just like we do by hand.
Approach#
Initialize an array of size n1 + n2
(where n1
and n2
are the lengths of num1
and num2
) to store the intermediate results.
Multiply each digit of num1
(from right to left) with each digit of num2
(from right to left), and add the product to the correct position in the result array.
Handle the carry for each position in the result array.
Build the final string by skipping leading zeros.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <string>
#include <vector>
using namespace std;
string multiply (string num1, string num2) {
int n1 = num1.size(), n2 = num2.size();
vector< int > ans(n1 + n2, 0 );
for (int i = n1 - 1 ; i >= 0 ; -- i) {
for (int j = n2 - 1 ; j >= 0 ; -- j) {
int d1 = num1[i] - '0' ;
int d2 = num2[j] - '0' ;
ans[i + j + 1 ] += d1 * d2;
}
}
int carry = 0 ;
for (int i = n1 + n2 - 1 ; i >= 0 ; -- i) {
int tmp = (ans[i] + carry) % 10 ;
carry = (ans[i] + carry) / 10 ;
ans[i] = tmp;
}
string res;
for (int num : ans) res += (num + '0' );
int idx = 0 ;
while (idx < res.size() - 1 && res[idx] == '0' ) ++ idx;
return res.substr(idx);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func multiply (num1 string , num2 string ) string {
n1 , n2 := len(num1 ), len(num2 )
ans := make([]int , n1 + n2 )
for i := n1 - 1 ; i >= 0 ; i -- {
for j := n2 - 1 ; j >= 0 ; j -- {
d1 := int(num1 [i ] - '0' )
d2 := int(num2 [j ] - '0' )
ans [i + j + 1 ] += d1 * d2
}
}
carry := 0
for i := n1 + n2 - 1 ; i >= 0 ; i -- {
tmp := (ans [i ] + carry ) % 10
carry = (ans [i ] + carry ) / 10
ans [i ] = tmp
}
res := ""
for _ , num := range ans {
res += string('0' + num )
}
idx := 0
for idx < len(res )- 1 && res [idx ] == '0' {
idx ++
}
return res [idx :]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public String multiply (String num1, String num2) {
int n1 = num1.length (), n2 = num2.length ();
int [] ans = new int [ n1 + n2] ;
for (int i = n1 - 1; i >= 0; i-- ) {
for (int j = n2 - 1; j >= 0; j-- ) {
int d1 = num1.charAt (i) - '0' ;
int d2 = num2.charAt (j) - '0' ;
ans[ i + j + 1] += d1 * d2;
}
}
int carry = 0;
for (int i = ans.length - 1; i >= 0; i-- ) {
int tmp = (ans[ i] + carry) % 10;
carry = (ans[ i] + carry) / 10;
ans[ i] = tmp;
}
StringBuilder sb = new StringBuilder();
for (int num : ans) sb.append (num);
while (sb.length () != 0 && sb.charAt (0) == '0' ) sb.deleteCharAt (0);
return sb.length () == 0 ? "0" : sb.toString ();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fun multiply (num1: String, num2: String): String {
val n1 = num1.length
val n2 = num2.length
val ans = IntArray(n1 + n2)
for (i in n1 - 1 downTo 0 ) {
for (j in n2 - 1 downTo 0 ) {
val d1 = num1[i] - '0'
val d2 = num2[j] - '0'
ans[i + j + 1 ] += d1 * d2
}
}
var carry = 0
for (i in n1 + n2 - 1 downTo 0 ) {
val tmp = (ans[i] + carry) % 10
carry = (ans[i] + carry) / 10
ans[i] = tmp
}
val sb = StringBuilder()
for (num in ans) sb.append(num)
while (sb.length != 0 && sb[0 ] == '0' ) sb.deleteCharAt(0 )
return if (sb.isEmpty()) "0" else sb.toString()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def multiply (num1: str, num2: str) -> str:
n1, n2 = len(num1), len(num2)
ans = [0 ] * (n1 + n2)
for i in range(n1 - 1 , - 1 , - 1 ):
for j in range(n2 - 1 , - 1 , - 1 ):
d1 = int(num1[i])
d2 = int(num2[j])
ans[i + j + 1 ] += d1 * d2
carry = 0
for i in range(n1 + n2 - 1 , - 1 , - 1 ):
tmp = (ans[i] + carry) % 10
carry = (ans[i] + carry) // 10
ans[i] = tmp
res = '' . join(str(num) for num in ans)
res = res. lstrip('0' )
return res if res else '0'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
pub fn multiply (num1: String, num2: String) -> String {
let n1 = num1.len();
let n2 = num2.len();
let mut ans = vec! [0 ; n1 + n2];
let num1 = num1.as_bytes();
let num2 = num2.as_bytes();
for i in (0 .. n1).rev() {
for j in (0 .. n2).rev() {
let d1 = (num1[i] - b '0' ) as i32 ;
let d2 = (num2[j] - b '0' ) as i32 ;
ans[i + j + 1 ] += d1 * d2;
}
}
let mut carry = 0 ;
for i in (0 .. n1 + n2).rev() {
let tmp = (ans[i] + carry) % 10 ;
carry = (ans[i] + carry) / 10 ;
ans[i] = tmp;
}
let mut res = String::new();
for & num in & ans {
res.push((num as u8 + b '0' ) as char );
}
let res = res.trim_start_matches('0' );
if res.is_empty() { "0" .to_string() } else { res.to_string() }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function multiply (num1 : string , num2 : string ): string {
const n1 = num1 .length , n2 = num2 .length ;
const ans = new Array(n1 + n2 ).fill (0 );
for (let i = n1 - 1 ; i >= 0 ; i -- ) {
for (let j = n2 - 1 ; j >= 0 ; j -- ) {
const d1 = Number(num1 [i ]);
const d2 = Number(num2 [j ]);
ans [i + j + 1 ] += d1 * d2 ;
}
}
let carry = 0 ;
for (let i = n1 + n2 - 1 ; i >= 0 ; i -- ) {
const tmp = (ans [i ] + carry ) % 10 ;
carry = Math.floor ((ans [i ] + carry ) / 10 );
ans [i ] = tmp ;
}
let res = ans .join ('' );
res = res .replace (/^0+/ , '' );
return res .length === 0 ? '0' : res ;
}
Complexity#
⏰ Time complexity: O(n1 * n2)
, where n1
and n2
are the lengths of the input strings.
🧺 Space complexity: O(n1 + n2)
, for the result array.
Method 2 – Left to Right Multiplication (With Reversing)#
Intuition#
By reversing both input strings, we can process digits from least significant to most significant (left to right in the reversed strings), which simplifies indexing and carry handling. This approach is closer to how we multiply numbers by hand, but with the digits stored in reverse order.
Approach#
Reverse both num1
and num2
.
Use an array to store intermediate results, adding products and carries as we go.
After all multiplications, build the result string from the array, skipping leading zeros.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
string multiply (string num1, string num2) {
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
int n1 = num1.size(), n2 = num2.size();
vector< int > result(n1 + n2, 0 );
for (int i = 0 ; i < n1; ++ i) {
int a = num1[i] - '0' ;
int carry = 0 ;
for (int j = 0 ; j < n2; ++ j) {
int b = num2[j] - '0' ;
result[i + j] += a * b + carry;
carry = result[i + j] / 10 ;
result[i + j] %= 10 ;
}
result[i + n2] += carry;
}
string res;
bool started = false;
for (int i = n1 + n2 - 1 ; i >= 0 ; -- i) {
if (! started && result[i] == 0 ) continue ;
started = true;
res += to_string(result[i]);
}
return res.empty() ? "0" : res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import "sort"
func reverse (s string ) string {
runes := []rune(s )
for i , j := 0 , len(runes )- 1 ; i < j ; i , j = i + 1 , j - 1 {
runes [i ], runes [j ] = runes [j ], runes [i ]
}
return string(runes )
}
func multiply (num1 string , num2 string ) string {
num1 = reverse (num1 )
num2 = reverse (num2 )
n1 , n2 := len(num1 ), len(num2 )
result := make([]int , n1 + n2 )
for i := 0 ; i < n1 ; i ++ {
a := int(num1 [i ] - '0' )
carry := 0
for j := 0 ; j < n2 ; j ++ {
b := int(num2 [j ] - '0' )
result [i + j ] += a * b + carry
carry = result [i + j ] / 10
result [i + j ] %= 10
}
result [i + n2 ] += carry
}
res := ""
started := false
for i := n1 + n2 - 1 ; i >= 0 ; i -- {
if !started && result [i ] == 0 {
continue
}
started = true
res += string('0' + result [i ])
}
if res == "" {
return "0"
}
return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public String multiply (String num1, String num2) {
num1 = new StringBuilder(num1).reverse ().toString ();
num2 = new StringBuilder(num2).reverse ().toString ();
int length1 = num1.length ();
int length2 = num2.length ();
int [] result = new int [ length1 + length2] ;
for (int i = 0; i < length1; i++ ) {
int a = num1.charAt (i) - '0' ;
int carry = 0;
for (int j = 0; j < length2; j++ ) {
int b = num2.charAt (j) - '0' ;
result[ i + j] += a * b + carry;
carry = result[ i + j] / 10;
result[ i + j] %= 10;
}
result[ i + length2] += carry;
}
StringBuilder s = new StringBuilder();
for (int i = length1 + length2 - 1; i >= 0; i-- ) {
if (i != 0 && result[ i] == 0 && s.length () == 0) continue ;
s.append (result[ i] );
}
return s.toString ();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
fun multiply (num1: String, num2: String): String {
val n1 = num1.length
val n2 = num2.length
val rev1 = num1.reversed()
val rev2 = num2.reversed()
val result = IntArray(n1 + n2)
for (i in 0 until n1) {
val a = rev1[i] - '0'
var carry = 0
for (j in 0 until n2) {
val b = rev2[j] - '0'
result[i + j] += a * b + carry
carry = result[i + j] / 10
result[i + j] %= 10
}
result[i + n2] += carry
}
val sb = StringBuilder()
for (i in n1 + n2 - 1 downTo 0 ) {
if (i != 0 && result[i] == 0 && sb.isEmpty()) continue
sb.append(result[i])
}
return sb.toString()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def multiply (num1: str, num2: str) -> str:
rev1 = num1[::- 1 ]
rev2 = num2[::- 1 ]
n1, n2 = len(rev1), len(rev2)
result = [0 ] * (n1 + n2)
for i in range(n1):
a = int(rev1[i])
carry = 0
for j in range(n2):
b = int(rev2[j])
result[i + j] += a * b + carry
carry = result[i + j] // 10
result[i + j] %= 10
result[i + n2] += carry
res = ''
started = False
for i in range(n1 + n2 - 1 , - 1 , - 1 ):
if not started and result[i] == 0 :
continue
started = True
res += str(result[i])
return res if res else '0'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
pub fn multiply (num1: String, num2: String) -> String {
let rev1: Vec< u8 > = num1.bytes().rev().collect();
let rev2: Vec< u8 > = num2.bytes().rev().collect();
let n1 = rev1.len();
let n2 = rev2.len();
let mut result = vec! [0 ; n1 + n2];
for i in 0 .. n1 {
let a = (rev1[i] - b '0' ) as i32 ;
let mut carry = 0 ;
for j in 0 .. n2 {
let b = (rev2[j] - b '0' ) as i32 ;
result[i + j] += a * b + carry;
carry = result[i + j] / 10 ;
result[i + j] %= 10 ;
}
result[i + n2] += carry;
}
let mut res = String::new();
let mut started = false ;
for i in (0 .. n1 + n2).rev() {
if ! started && result[i] == 0 {
continue ;
}
started = true ;
res.push_str(& result[i].to_string());
}
if res.is_empty() { "0" .to_string() } else { res }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function reverse (s : string ): string {
return s .split ('' ).reverse ().join ('' );
}
function multiply (num1 : string , num2 : string ): string {
num1 = reverse (num1 );
num2 = reverse (num2 );
const n1 = num1 .length , n2 = num2 .length ;
const result = new Array(n1 + n2 ).fill (0 );
for (let i = 0 ; i < n1 ; i ++ ) {
const a = Number(num1 [i ]);
let carry = 0 ;
for (let j = 0 ; j < n2 ; j ++ ) {
const b = Number(num2 [j ]);
result [i + j ] += a * b + carry ;
carry = Math.floor (result [i + j ] / 10 );
result [i + j ] %= 10 ;
}
result [i + n2 ] += carry ;
}
let res = '' ;
let started = false ;
for (let i = n1 + n2 - 1 ; i >= 0 ; i -- ) {
if (! started && result [i ] === 0 ) continue ;
started = true ;
res += result [i ].toString ();
}
return res === '' ? '0' : res ;
}
Complexity#
⏰ Time complexity: O(n1 * n2)
, where n1
and n2
are the lengths of the input strings.
🧺 Space complexity: O(n1 + n2)
, for the result array.
Method 3 – Left to Right in Result Array (No Reversing)#
Intuition#
Instead of reversing the input strings, we can traverse the digits from the end (rightmost) and fill the result array from left to right. This approach keeps the original order of the input strings and only manipulates indices in the result array.
Approach#
Traverse num1
and num2
from the end (rightmost digit) to the start.
For each digit, multiply and add to the correct position in the result array, handling carry as you go.
After all multiplications, build the result string from the result array, skipping leading zeros.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <string>
#include <vector>
using namespace std;
string multiply (string num1, string num2) {
if (num1.empty() || num2.empty()) return "0" ;
int n1 = num1.size(), n2 = num2.size();
vector< int > result(n1 + n2, 0 );
for (int i = 0 ; i < n1; ++ i) {
int a = num1[n1 - i - 1 ] - '0' ;
int carry = 0 ;
for (int j = 0 ; j < n2; ++ j) {
int b = num2[n2 - j - 1 ] - '0' ;
result[i + j] += a * b + carry;
carry = result[i + j] / 10 ;
result[i + j] %= 10 ;
}
result[i + n2] += carry;
}
string res;
bool started = false;
for (int i = n1 + n2 - 1 ; i >= 0 ; -- i) {
if (! started && result[i] == 0 ) continue ;
started = true;
res += to_string(result[i]);
}
return res.empty() ? "0" : res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func multiply (num1 string , num2 string ) string {
if len(num1 ) == 0 || len(num2 ) == 0 {
return "0"
}
n1 , n2 := len(num1 ), len(num2 )
result := make([]int , n1 + n2 )
for i := 0 ; i < n1 ; i ++ {
a := int(num1 [n1 - i - 1 ] - '0' )
carry := 0
for j := 0 ; j < n2 ; j ++ {
b := int(num2 [n2 - j - 1 ] - '0' )
result [i + j ] += a * b + carry
carry = result [i + j ] / 10
result [i + j ] %= 10
}
result [i + n2 ] += carry
}
res := ""
started := false
for i := n1 + n2 - 1 ; i >= 0 ; i -- {
if !started && result [i ] == 0 {
continue
}
started = true
res += string('0' + result [i ])
}
if res == "" {
return "0"
}
return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public String multiply (String num1, String num2) {
if (num1 == null || num2 == null ) {
return null ;
}
int length1 = num1.length ();
int length2 = num2.length ();
int [] result = new int [ length1 + length2] ;
for (int i = 0; i < length1; i++ ) {
int a = num1.charAt (length1 - i - 1) - '0' ;
int carry = 0;
for (int j = 0; j < length2; j++ ) {
int b = num2.charAt (length2 - j - 1) - '0' ;
result[ i + j] += a * b + carry;
carry = result[ i + j] / 10;
result[ i + j] %= 10;
}
result[ i + length2] += carry;
}
StringBuilder s = new StringBuilder();
for (int i = length1 + length2 - 1; i >= 0; i-- ) {
if (i != 0 && result[ i] == 0 && s.length () == 0) continue ;
s.append (result[ i] );
}
return s.toString ();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
fun multiply (num1: String, num2: String): String {
if (num1.isEmpty() || num2.isEmpty()) return "0"
val n1 = num1.length
val n2 = num2.length
val result = IntArray(n1 + n2)
for (i in 0 until n1) {
val a = num1[n1 - i - 1 ] - '0'
var carry = 0
for (j in 0 until n2) {
val b = num2[n2 - j - 1 ] - '0'
result[i + j] += a * b + carry
carry = result[i + j] / 10
result[i + j] %= 10
}
result[i + n2] += carry
}
val sb = StringBuilder()
for (i in n1 + n2 - 1 downTo 0 ) {
if (i != 0 && result[i] == 0 && sb.isEmpty()) continue
sb.append(result[i])
}
return sb.toString()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def multiply (num1: str, num2: str) -> str:
if not num1 or not num2:
return '0'
n1, n2 = len(num1), len(num2)
result = [0 ] * (n1 + n2)
for i in range(n1):
a = int(num1[n1 - i - 1 ])
carry = 0
for j in range(n2):
b = int(num2[n2 - j - 1 ])
result[i + j] += a * b + carry
carry = result[i + j] // 10
result[i + j] %= 10
result[i + n2] += carry
res = ''
started = False
for i in range(n1 + n2 - 1 , - 1 , - 1 ):
if not started and result[i] == 0 :
continue
started = True
res += str(result[i])
return res if res else '0'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
pub fn multiply (num1: String, num2: String) -> String {
if num1.is_empty() || num2.is_empty() {
return "0" .to_string();
}
let n1 = num1.len();
let n2 = num2.len();
let num1 = num1.as_bytes();
let num2 = num2.as_bytes();
let mut result = vec! [0 ; n1 + n2];
for i in 0 .. n1 {
let a = (num1[n1 - i - 1 ] - b '0' ) as i32 ;
let mut carry = 0 ;
for j in 0 .. n2 {
let b = (num2[n2 - j - 1 ] - b '0' ) as i32 ;
result[i + j] += a * b + carry;
carry = result[i + j] / 10 ;
result[i + j] %= 10 ;
}
result[i + n2] += carry;
}
let mut res = String::new();
let mut started = false ;
for i in (0 .. n1 + n2).rev() {
if ! started && result[i] == 0 {
continue ;
}
started = true ;
res.push_str(& result[i].to_string());
}
if res.is_empty() { "0" .to_string() } else { res }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function multiply (num1 : string , num2 : string ): string {
if (num1 .length === 0 || num2 .length === 0 ) return '0' ;
const n1 = num1 .length , n2 = num2 .length ;
const result = new Array(n1 + n2 ).fill (0 );
for (let i = 0 ; i < n1 ; i ++ ) {
const a = Number(num1 [n1 - i - 1 ]);
let carry = 0 ;
for (let j = 0 ; j < n2 ; j ++ ) {
const b = Number(num2 [n2 - j - 1 ]);
result [i + j ] += a * b + carry ;
carry = Math.floor (result [i + j ] / 10 );
result [i + j ] %= 10 ;
}
result [i + n2 ] += carry ;
}
let res = '' ;
let started = false ;
for (let i = n1 + n2 - 1 ; i >= 0 ; i -- ) {
if (! started && result [i ] === 0 ) continue ;
started = true ;
res += result [i ].toString ();
}
return res === '' ? '0' : res ;
}
Complexity#
⏰ Time complexity: O(n1 * n2)
, where n1
and n2
are the lengths of the input strings.
🧺 Space complexity: O(n1 + n2)
, for the result array.