前言
🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀
🌟 欢迎大家关注我的微信公众号【JavaPersons】!在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。
💡 无论你是刚刚踏入编程世界的新人,还是希望进一步提升自己的资深开发者,在这里都能找到适合你的内容。我们共同探讨技术难题,一起进步,携手度过互联网行业的每一个挑战。
📣 如果你觉得我的文章对你有帮助,请不要吝啬你的点赞👍分享💕和评论哦! 让我们一起打造一个充满正能量的技术社区吧!
目录标题
亲爱的同学们👩🎓👨🎓,当你们准备踏入互联网大厂的面试征程时,会遇到各种具有挑战性的算法问题。今天,我们就来深入探讨一个在大厂面试中可能出现的经典问题:给定两个以字符串形式表示的非负整数num1和num2,返回它们的乘积,且乘积也表示为字符串形式,同时不能使用任何内置的BigInteger库或直接将输入转换为整数。这个问题不仅考验大家对 Java 基础语法的掌握程度,还涉及到数据结构与算法的巧妙运用。让我们一起开启这场充满智慧的编程之旅吧!💪
1. 题目描述 📜
给定两个以字符串形式表示的非负整数 num1
和 num2
,返回它们的乘积,结果也表示为字符串形式。
示例
输入: num1 = "123", num2 = "456"
输出: "56088"
输入: num1 = "2", num2 = "3"
输出: "6"
注意
- 输入字符串只包含数字
0-9
。 - 输入字符串不包含任何前导零,除了数字
0
本身。 - 不能使用任何内置的
BigInteger
库或直接将输入转换为整数。
2. 考察知识点 🧠
要解决这个问题,我们需要掌握以下几个方面的知识:
- Java 基础语法:
- 字符串的操作,包括获取字符串长度、访问特定位置的字符等。
- 基本数据类型的转换,虽然不能直接将字符串转换为整数,但可能需要进行字符到数字的小范围转换。
- 字符串拼接的方法。
- 数据结构:
- 理解如何使用数组等数据结构来辅助计算。
- 可能需要考虑使用二维数组来存储中间结果。
- 算法思维:
- 设计合适的算法来实现字符串数字的乘法运算,尤其是处理不同长度的字符串数字。
- 考虑算法的时间复杂度和空间复杂度。🧐
3. 题意分析 🤔
题目要求我们接收两个字符串参数,这两个参数代表了两个非负整数(注意这里没有说正整数,所以0也是合法输入)。我们需要计算它们的乘积,并且把结果同样以字符串的形式返回。这意味着我们需要处理字符串的每一位数字,并进行逐位相乘,同时处理进位和部分积的累加问题。
4. 解题思路 💡
4.1 优化的手工乘法
- 模拟我们在纸上进行竖式乘法的过程。
- 将
num1
的每一位与num2
相乘,得到中间结果,然后将这些中间结果相加得到最终乘积。 - 创建一个
StringMultiplier
类来封装这个功能。😃
步骤详解
- 初始化变量:定义一个数组
result
来存储最终结果,长度为num1.length() + num2.length()
。 - 逐位相乘:从右到左遍历
num1
的每一位数字,再从右到左遍历num2
的每一位数字,计算部分积并直接累加到result
中对应的位置。 - 处理进位:对
result
进行进位处理。 - 去除前导零:如果结果有前导零,则去除这些前导零。
- 返回结果:将结果转换为字符串并返回。
num1 = “123”, num2 = “456” 过程
1 2 3
× 4 5 6
------
7 3 8 (123 * 6)
6 1 5 (123 * 5, 向左移一位)
4 9 2 (123 * 4, 向左移两位)
------
5 6 0 8 8
5. 题解代码 📝
为了更好地展示面向对象的思想,我们可以将上述方法封装在一个类中。这样不仅可以提高代码的可复用性,还可以使代码结构更加清晰。
5.1 优化的手工乘法
class StringMultiplier {
public String multiplyStrings(String num1, String num2) {
int[] result = new int[num1.length() + num2.length()];
for (int i = num1.length() - 1; i >= 0; i--) {
int carry = 0;
int n1 = num1.charAt(i) - '0';
for (int j = num2.length() - 1; j >= 0; j--) {
int n2 = num2.charAt(j) - '0';
int sum = n1 * n2 + result[i + j + 1] + carry;
carry = sum / 10;
result[i + j + 1] = sum % 10;
}
if (carry > 0) {
result[i] += carry;
}
}
StringBuilder sb = new StringBuilder();
boolean leadingZero = true;
for (int digit : result) {
if (digit == 0 && leadingZero) continue;
leadingZero = false;
sb.append(digit);
}
return sb.length() == 0? "0" : sb.toString();
}
}
6. 总结 🎉
通过这个例子,我们不仅学习到了如何利用Java标准库解决问题,也了解了如何自己动手实现复杂逻辑。
6.1 优点与缺点
- 优化的手工乘法:
- 优点:空间复杂度较低,直接在结果数组上进行累加。
- 缺点:代码相对复杂,容易出错。
7. 常见面试问题及解答 🙋♂️
- Q: 为什么不能直接使用
BigInteger
?- A: 使用
BigInteger
虽然简单高效,但在某些面试或特定环境中可能不允许使用外部库。此外,手动实现可以更深入地理解底层原理。
- A: 使用
- Q: 如何处理输入中的非法字符?
- A: 可以在函数开始时增加输入验证,确保输入字符串只包含数字字符。如果发现非法字符,抛出异常或返回错误信息。
- Q: 如果输入非常长,如何优化性能?
- A: 对于非常长的输入,可以考虑使用分块处理的方式,将字符串分成多个小段分别处理,减少内存消耗。此外,可以使用多线程来并行处理不同的部分,进一步提高性能。
8. 结语 🎊
希望这篇文章能够帮助大家在面试中取得好成绩,顺利进入自己心仪的互联网大厂。如果大家还有其他问题或更好的解法,欢迎在评论区留言交流。💬
祝大家面试顺利,未来可期!🎉
乐于分享和输出干货的Java技术公众号:JavaPersons