今天讲一个标注难度是难,实际上还挺好写的一个题目,模拟二进制加法
题目分析
我们面临的任务是将两个二进制字符串相加,并输出其对应的十进制和。输入的二进制字符串可能非常长,因此需要设计一个高效的算法。
- 输入:两个二进制字符串
binary1和binary2,可能具有不同的长度。 - 输出:这两个二进制字符串的和,以十进制的形式表示。
二进制加法的基础
二进制加法与十进制加法类似,但由于只有两个数(0 和 1),规则更为简单:
- 0 + 0 = 0;
- 1 + 0 = 1 或 0 + 1 = 1;
- 1 + 1 = 10,即进位。
因此,二进制加法的步骤大致如下:
- 从二进制数的最低位开始相加。
- 如果两位的和为 2,产生进位,并将该位的结果设置为 0。
- 如果两位的和为 1,结果为 1,不产生进位。
- 如果没有更多的位可加但仍有进位,则在最终结果的最高位添加进位。
算法设计
为了解决这个问题,我们可以使用模拟二进制加法的方式,逐位相加。以下是我们的基本思路:
- 将两个二进制字符串从右向左反转,以便我们从最低位开始逐位加法
- 对齐两个二进制字符串,确保它们的长度相同,如果长度不等,则在较短的字符串末尾补充零
- 遍历每一位,模拟加法,并处理进位
- 将最终的结果累加并转为十进制数
代码实现
def solution(binary1, binary2):
# 反转字符串并转换为列表
Array1 = list(reversed(list(binary1)))
Array2 = list(reversed(list(binary2)))
# 补齐位数,确保两者长度一致
len_diff = len(Array1) - len(Array2)
if len_diff > 0:
Array2.extend([0] * len_diff) # 在较短的二进制串后面补零
elif len_diff < 0:
Array1.extend([0] * (-len_diff)) # 在较短的二进制串后面补零
# 将字符转为数字
Array1 = list(map(int, Array1))
Array2 = list(map(int, Array2))
ans = 0 # 用于存储结果
adv = 0 # 进位值
# 从低位到高位逐位计算
for i in range(len(Array1)):
a, b = cal(Array1[i], Array2[i], adv)
ans += a * (2 ** i) # 根据位的位置累加到结果中
adv = b # 更新进位
# 最后处理进位
ans += adv * (2 ** (i + 1) if i >= 0 else 0)
return str(ans)
def cal(a, b, c):
""" 计算每一位的加法以及进位 (三引号注释)"""
res = [0, 0] # res[0] 是该位的结果,res[1] 是进位
if a + b + c == 1 or a + b + c == 3:
res[0] = 1
if a + b + c >= 2:
res[1] = 1
return res
if __name__ == "__main__":
# 测试用例
print(solution("101", "110") == "11")
print(solution("111111", "10100") == "83")
print(solution("111010101001001011", "100010101001") == "242420")
print(solution("111010101001011", "10010101001") == "31220")
代码详解
-
反转和补齐:
- 首先反转输入的二进制字符串
binary1和binary2,这样便可以从最低位开始进行加法 - 接着,如果两个二进制数的长度不相等,补零,让它们的长度一致。这一步是为了保证两数加法时不会丢失高位信息
- 首先反转输入的二进制字符串
-
模拟加法:
- 使用
cal函数来计算每一位的加法结果和进位。如果当前位的和为 1 或 3(即存在进位或本身是 1),则该位的结果为 1;如果和为 2,产生进位 - 对于每一位,将结果乘以对应的权重(即
2^i)加到ans中,并更新进位adv
- 使用
-
进位处理:
- 最后,我们需要检查是否有多余的进位,如果有,则将其加到最终结果中。
时间复杂度分析
- 假设
n是较长二进制字符串的长度。 - 反转和补齐操作的时间复杂度是 O(n)。
- 遍历二进制数并计算每一位的加法和进位,时间复杂度也是 O(n)。
- 因此,该算法的整体时间复杂度为 O(n),这是一个线性时间复杂度的算法,满足题目要求。
测试用例
solution("101", "110"):
输入的两个二进制字符串分别为 "101" 和 "110"。它们相加后为 "1011",对应的十进制数为 11。solution("111111", "10100"):
输入的二进制字符串分别为 "111111" 和 "10100"。相加后的结果为 "1010011",对应的十进制数为 83。solution("111010101001001011", "100010101001"):
输入的二进制字符串分别为 "111010101001001011" 和 "100010101001"。它们相加后为 "111010111101110110",对应的十进制数为 242420。solution("111010101001011", "10010101001"):
输入的二进制字符串分别为 "111010101001011" 和 "10010101001"。它们相加后为 "11111111111001001",对应的十进制数为 31220。
结论
今天介绍了如何实现一个时间复杂度O(n^2)以内的算法来处理二进制字符串的加法。通过逐位模拟二进制加法,并利用线索化的思想来处理进位,我们能够避免使用高精度整数运算,确保算法在处理非常长的二进制字符串时仍能保持线性时间复杂度 O(n)。这种方法不仅符合时间复杂度要求,还能适应不同长度的输入,具备较好的扩展性。