【题目】
给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。
示例 1:
输入: a = "11", b = "1"
输出: "100"
示例 2:
输入: a = "1010", b = "1011"
输出: "10101"
提示:
1 <= a.length, b.length <= 10^4a和b仅由字符'0'或'1'组成- 字符串如果不是
"0",就不含前导零
【题目解析】
解题方法
解决算法: 双指针逐位相加法
算法描述:
这个问题可以通过模拟二进制加法的过程来解决。从两个字符串的末尾开始,即最低位,向前逐位相加,并处理进位问题。使用两个指针分别指向两个字符串的末尾,并在遍历的过程中逐位计算和,如果和大于1,则记录进位,并将当前位的计算结果对2取余得到当前位的值。直到两个字符串都遍历完成。如果最后还有进位,需要在结果前面加上一个'1'。
具体步骤:
-
初始化两个指针分别指向a和b的末尾,以及一个变量carry来存储进位,初始为0。
-
当两个指针中至少有一个未遍历完时,执行以下操作:
- 分别取出a和b当前指针指向的字符,转换为数字后相加,再加上carry的值。
- 更新carry,如果和大于等于2,则carry为1,否则为0。
- 将当前位的和对2取余,然后添加到结果字符串的前面。
- 移动指针继续遍历。
-
如果遍历完成后carry为1,将'1'添加到结果字符串的前面。
-
返回结果字符串。
class Solution:
def addBinary(self, a: str, b: str) -> str:
# 初始化两个指针分别指向a和b的末尾
i, j = len(a) - 1, len(b) - 1
# 初始化进位为0
carry = 0
# 初始化结果字符串为空
result = ""
# 当至少有一个指针没有遍历完或者还有进位时
while i >= 0 or j >= 0 or carry:
# 如果a的当前位有效
if i >= 0:
# 将a的当前位加到进位上
carry += int(a[i])
# 指针i向前移动
i -= 1
# 如果b的当前位有效
if j >= 0:
# 将b的当前位加到进位上
carry += int(b[j])
# 指针j向前移动
j -= 1
# 将当前位的结果(carry % 2)加到结果字符串的前面
result = str(carry % 2) + result
# 更新进位,整除2得到新的进位
carry //= 2
# 返回结果字符串
return result
执行效率
【总结】
适用问题类型:
这种方法特别适用于处理二进制字符串的数学运算问题,尤其是当直接的数值运算可能导致整数溢出或者数值过大以至于无法使用标准数据类型表示时。典型应用包括二进制数的加法、减法、乘法等基本算术运算,以及更复杂的二进制数处理场景,如二进制下的位运算问题、大数运算、以及加密算法中的数值操作等。
解决算法: 双指针逐位相加法
算法特点:
- 精确性: 直接在二进制字符串上操作,避免了数值转换过程中可能出现的精度丢失或溢出问题。
- 灵活性: 无需预先知道输入数值的大小,能够灵活处理任意长度的二进制字符串。
- 简洁直观: 算法模拟了手工二进制加法的自然过程,逻辑简单易于理解和实现。
时间复杂度与空间复杂度:
- 时间复杂度: O(max(n, m)),其中n和m分别是输入的两个二进制字符串的长度。在最坏的情况下,需要遍历两个字符串的每一位进行计算。
- 空间复杂度: O(max(n, m)),需要存储加法结果的字符串,其长度最多为较长输入字符串的长度加1(考虑到可能的进位)。
实践意义:
- 大数处理: 这种方法可以处理超出常规数值类型表示范围的大数运算,特别是在加密和网络通信等领域,经常需要处理大量的二进制数据。
- 算法教育: 对于学习计算机科学和编程的学生和新手,掌握二进制加法及相关位运算是基础且重要的技能,有助于加深对计算机内部数值表示和处理机制的理解。
- 编程面试: 在编程面试中,二进制操作是常见的题目类型之一,掌握这类题目的解题技巧可以帮助面试者在面试中脱颖而出。
- 软件开发: 在实际的软件开发过程中,特别是涉及底层数据处理、硬件接口交互、系统优化等领域,经常需要直接对二进制数据进行操作和运算。掌握二进制加法的原理和实现方法,可以帮助开发者更有效地解决这类问题。