Leetcode43. 字符串相乘
题目:
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
说明:
num1 和 num2 的长度小于110。
num1 和 num2 只包含数字 0-9。
num1 和 num2 均不以零开头,除非是数字 0 本身。
不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
方法一:
和字符串相加类似:
Leetcode415. 字符串相加
题解:
竖式运算思想,以 num1 为 123,num2 为 456 为例分析:
遍历 num2 每一位与 num1 进行相乘,将每一步的结果进行累加。
注意:
num2 除了第一位的其他位与 num1 运算的结果需要 补0
计算字符串数字累加其实就是 415. 字符串相加
方法二:
该算法是通过两数相乘时,乘数某位与被乘数某位相乘,与产生结果的位置的规律来完成。具体规律如下:
- 乘数 num1 位数为 M,被乘数 num2 位数为 N, num1 x num2 结果 res 最大总位数为 M+N
- num1[i] x num2[j] 的结果为 tmp(位数为两位,“0x”,"xy"的形式),其第一位位于 res[i+j],第二位位于 res[i+j+1]。
结合下图更容易理解
java代码:
方法一:
public static String multiply(String s1, String s2) {
if (s1 == "0" || s2 == "0") return "0";
String result = "0";
for (int i = s2.length() - 1; i >= 0; i--) {
StringBuffer buffer = new StringBuffer();
for (int j = s2.length() - 1 - i; j > 0; j--) {
buffer.append(0);
}
int n2 = s2.charAt(i) - '0';
int carry = 0;
int len = s1.length() - 1;
while (len >= 0 || carry > 0) {
int n1 = len < 0 ? 0 : s1.charAt(len) - '0';
int a = n1 * n2 + carry;
buffer.append(a % 10);
carry = a / 10;
len--;
}
result = addStrings(result, buffer.reverse().toString());
}
return result;
}
public static String addStrings(String s1, String s2) {
int i = s1.length() - 1;
int j = s2.length() - 1;
StringBuffer buffer = new StringBuffer();
int n1, n2;
int carry = 0;
while (i >= 0 || j >= 0) {
if (i >= 0) {
n1 = s1.charAt(i) - '0';
} else {
n1 = 0;
}
if (j >= 0) {
n2 = s2.charAt(j) - '0';
} else {
n2 = 0;
}
int num = n1 + n2 + carry;
carry = num / 10;
int res = num % 10;
buffer.append(res);
i--;
j--;
}
if (carry > 0) buffer.append(carry);
return buffer.reverse().toString();
}
方法二:
public static String multiply2(String s1, String s2) {
if (s1 == "0" || s2 == "0") return "0";
int[] res = new int[s1.length() + s2.length()];
for (int i = s1.length() - 1; i >= 0; i--) {
for (int j = s2.length() - 1; j >= 0; j--) {
int n1 = s1.charAt(i) - '0';
int n2 = s2.charAt(j) - '0';
int num = n1 * n2 + res[i + j + 1];
res[i + j + 1] = num % 10;
res[i + j] = res[i + j] + num / 10;
}
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < res.length; i++) {
if (i == 0 && res[i] == 0) continue;
buffer.append(res[i]);
}
return buffer.toString();
}
scala代码:
方法一:
/**
*
* @param num1
* @param num2
* @return
*/
def multiply(num1: String, num2: String): String = {
var result = "0"
if (num1 != "0" && num2 != "0") {
//
for (i <- 0 until num2.length reverse) {
//进位
var carry = 0
// 保存 num2 第i位数字与 num1 相乘的结果
val temp = new StringBuilder()
//对nums2中的每一位补0
for (j <- 0 until num2.length - 1 - i) {
temp.append(0)
}
val n2 = num2(i) - '0'
var k = num1.length - 1
while (k >= 0 || carry != 0) {
val n1 = if (k < 0) 0 else num1.charAt(k) - '0'
val product = (n1 * n2 + carry) % 10
temp.append(product)
carry = (n1 * n2 + carry) / 10
k = k - 1
}
//将当前结果与新计算的结果求和作为新的结果
result = addStrings(result, temp.reverse.toString())
}
}
result
}
def addStrings(str1: String, str2: String): String = {
val builder = new StringBuilder()
var carry = 0
var i = str1.length - 1
var j = str2.length - 1
while (i >= 0 || j >= 0 || carry != 0) {
val n1 = if (i < 0) 0 else str1.charAt(i) - '0'
val n2 = if (j < 0) 0 else str2.charAt(j) - '0'
val product = (n1 + n2 + carry) % 10
builder.append(product)
carry = (n1 + n2 + carry) / 10
i = i - 1
j = j - 1
}
builder.reverse.toString()
}
方法二:
/**
*
* @param num1
* @param num2
* @return
*/
def multiply2(num1: String, num2: String): String = {
if (num1 == "0" || num2 == "0") {
"0"
} else {
val arr = new Array[Int](num1.length + num2.length)
for (i <- 0 until num1.length reverse) {
for (j <- 0 until num2.length reverse) {
val n1 = num1.charAt(i) - '0'
val n2 = num2.charAt(j) - '0'
val sum = n1 * n2 + arr(i + j + 1)
arr(i + j + 1) = sum % 10
arr(i + j) = arr(i + j) + sum / 10
}
}
val str = new StringBuilder()
for (i <- 0 until arr.length) {
//去掉首位为0的情况
breakable {
if (i == 0 && arr(i) == 0) {
break()
}
str.append(arr(i))
}
}
str.toString()
}
}