前言
🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀
🌟 欢迎大家关注我的微信公众号【JavaPersons】!在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。
💡 无论你是刚刚踏入编程世界的新人,还是希望进一步提升自己的资深开发者,在这里都能找到适合你的内容。我们共同探讨技术难题,一起进步,携手度过互联网行业的每一个挑战。
📣 如果你觉得我的文章对你有帮助,请不要吝啬你的点赞👍分享💕和评论哦! 让我们一起打造一个充满正能量的技术社区吧!
目录标题
- 前言
- 引言 📘
- 1. 题目描述 📜
- 示例
- 注意
- 2. 考察知识点 🧠
- 3. 题意分析 🤔
- 4. 解题思路 💡
- ~~4.1 直接使用内置方法(可以说但是最好不要真的面试用这个解)~~
- 步骤详解
- 4.2 手动实现加法运算
- 步骤详解
- 5. 题解代码 📝
- 6. 总结 🎉
- 6.1 优点与缺点
- 6.2 适用场景
- 7. 实战练习 🚀
- 8. 常见面试问题及解答 🙋♂️
引言 📘
在准备互联网大厂的技术面试时,掌握一些常见的算法问题是非常重要的。今天我们将探讨一个经典的问题:如何将两个以字符串形式表示的非负整数相加,并返回它们的和,同样以字符串形式表示。这个问题不仅考察了基本的数据类型转换能力,还涉及到了字符串处理、数学运算以及算法设计。通过这篇文章,你将学到两种高效的解决方案,并且能够深刻理解每一步背后的原理。
1. 题目描述 📜
给定两个以字符串形式表示的非负整数 num1
和 num2
,编写一个函数来计算它们的和,并以字符串形式返回结果。
示例
输入: num1 = "123", num2 = "456"
输出: "579"
输入: num1 = "11", num2 = "123"
输出: "134"
注意
- 输入字符串只包含数字
0-9
。 - 输入字符串不包含任何前导零,除了数字
0
本身。
2. 考察知识点 🧠
要解决这个问题,我们需要掌握以下几个方面的知识:
- 字符串操作
- 数字系统及其表示
- 基本算术运算
- Java语言基础
- 面向对象编程思想
- 算法设计与优化
3. 题意分析 🤔
题目要求我们接收两个字符串参数,这两个参数代表了两个非负整数(注意这里没有说正整数,所以0也是合法输入)。我们需要计算它们的和,并且把结果同样以字符串的形式返回。这意味着我们需要处理字符串的每一位数字,并进行逐位相加,同时处理进位问题。
4. 解题思路 💡
针对这一问题,我们可以考虑两种不同的解决方案:一种是利用Java内置的方法快速解决问题,另一种是从底层手动实现加法运算。
4.1 直接使用内置方法(可以说但是最好不要真的面试用这个解)
步骤详解
- 导入必要的库:
java.math.BigInteger
。 - 创建BigInteger对象:将输入的字符串转换为
BigInteger
对象。 - 执行加法运算:使用
add
方法进行加法运算。 - 转换回字符串:将结果转换回字符串并返回。
import java.math.BigInteger;
public String addStringsUsingBigInteger(String num1, String num2) {
// 创建BigInteger对象
BigInteger a = new BigInteger(num1);
BigInteger b = new BigInteger(num2);
// 执行加法运算
BigInteger sum = a.add(b);
// 将结果转换为字符串
return sum.toString();
}
4.2 手动实现加法运算
步骤详解
- 初始化变量:定义一个
StringBuilder
来构建结果字符串,以及一个carry
变量来记录进位。 - 从最低位开始遍历:从字符串的末尾开始向前遍历,直到所有位都处理完毕。
- 逐位相加:获取当前位的数值,如果已经超出字符串长度,则视为0。
- 处理进位:计算当前位的和与新的进位值。
- 构建结果:将当前位的结果添加到
StringBuilder
中。 - 反转结果:由于是从低位到高位构建的结果,最后需要反转字符串。
public String addStringsManually(String num1, String num2) {
StringBuilder result = new StringBuilder();
int i = num1.length() - 1;
int j = num2.length() - 1;
int carry = 0; // 进位标志
while (i >= 0 || j >= 0 || carry > 0) {
// 获取当前位的数值
int digit1 = i >= 0 ? num1.charAt(i--) - '0' : 0;
int digit2 = j >= 0 ? num2.charAt(j--) - '0' : 0;
// 计算当前位的和与新的进位值
int sum = digit1 + digit2 + carry;
carry = sum / 10; // 计算新的进位值
result.append(sum % 10); // 将当前位添加到结果中
}
// 结果是反向构建的,需要反转
return result.reverse().toString();
}
5. 题解代码 📝
为了更好地展示面向对象的思想,我们可以将上述方法封装在一个类中。这样不仅可以提高代码的可复用性,还可以使代码结构更加清晰。
public class StringAdder {
// 使用内置方法
public String addStringsUsingBigInteger(String num1, String num2) {
BigInteger a = new BigInteger(num1);
BigInteger b = new BigInteger(num2);
return a.add(b).toString();
}
// 手动实现加法运算
public String addStringsManually(String num1, String num2) {
StringBuilder result = new StringBuilder();
int i = num1.length() - 1;
int j = num2.length() - 1;
int carry = 0; // 进位标志
while (i >= 0 || j >= 0 || carry > 0) {
int digit1 = i >= 0 ? num1.charAt(i--) - '0' : 0;
int digit2 = j >= 0 ? num2.charAt(j--) - '0' : 0;
int sum = digit1 + digit2 + carry;
carry = sum / 10; // 计算新的进位值
result.append(sum % 10); // 将当前位添加到结果中
}
return result.reverse().toString();
}
}
6. 总结 🎉
通过这个例子,我们不仅学习到了如何利用Java标准库解决问题,也了解了如何自己动手实现复杂逻辑。这两种方式都是宝贵的技能,在未来的学习或工作中都能发挥作用。
6.1 优点与缺点
-
直接使用内置方法:
- 优点:简洁高效,易于理解和实现。
- 缺点:依赖于特定库,可能不够灵活。
-
手动实现加法运算:
- 优点:锻炼编程思维,可以更深入地理解底层原理,面试官一般喜欢。
- 缺点:代码相对复杂,容易出错。
6.2 适用场景
- 直接使用内置方法:适用于日常开发,特别是当输入数据不会特别大时。
- 手动实现加法运算:适用于需要深入了解底层原理的情况,或者在某些特定环境下无法使用外部库时。
7. 实战练习 🚀
尝试编写测试用例,验证你的函数是否正确处理各种情况,包括边界条件如空字符串、单个字符等。
public static void main(String[] args) {
StringAdder adder = new StringAdder();
// 测试用例
System.out.println(adder.addStringsUsingBigInteger("123", "456")); // 输出: "579"
System.out.println(adder.addStringsManually("11", "123")); // 输出: "134"
System.out.println(adder.addStringsUsingBigInteger("0", "0")); // 输出: "0"
System.out.println(adder.addStringsManually("999", "1")); // 输出: "1000"
}
8. 常见面试问题及解答 🙋♂️
- Q: 为什么选择
BigInteger
而不是Integer
或Long
?- A:
BigInteger
可以处理任意大小的整数,而Integer
和Long
有固定的范围限制。对于非常大的数字,BigInteger
是更好的选择。
- A:
- Q: 如何处理输入中的非法字符?
- A: 可以在函数开始时增加输入验证,确保输入字符串只包含数字字符。如果发现非法字符,抛出异常或返回错误信息。
- Q: 如果输入非常长,如何优化性能?
- A: 对于非常长的输入,可以考虑使用分块处理的方式,将字符串分成多个小段分别处理,减少内存消耗。
乐于分享和输出干货的Java技术公众号:JavaPersons