二进制之和 | 豆包MarsCode AI刷题

39 阅读8分钟

二进制之和 | 豆包MarsCode AI刷题

二进制之和

问题描述

小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n2)O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。


测试样例

样例1:

输入:binary1 = "101" ,binary2 = "110"
输出:'11'

样例2:

输入:binary1 = "111111" ,binary2 = "10100"
输出:'83'

样例3:

输入:binary1 = "111010101001001011" ,binary2 = "100010101001"
输出:'242420'

样例4:

输入:binary1 = "111010101001011" ,binary2 = "10010101001"
输出:'31220'

样例5:

输入:binary1 = "11" ,binary2 = "1"
输出:'4'

解决思路

我觉得这个就是一个普通的模拟题,通过计算两个二进制数的每一位,同时记录进位,就像竖式计算一样,可以得到最终的结果,题目要求时间复杂度不超过O(n2)O(n^2),AI也给出了类似的思路


Prompt:

需要一点思路提示

MarsCode AI

好的,让我们来分析一下这个问题的解题思路。

问题理解

你需要将两个二进制字符串相加,并将结果以十进制的形式返回。由于二进制字符串可能非常长,常规的整数类型可能无法处理,因此需要设计一个算法来处理大数相加。

数据结构选择
  • 字符串:用于存储二进制字符串。
  • 列表:用于存储中间结果,便于处理进位。
算法步骤
  1. 反转字符串:从最低位开始相加,因此需要先反转两个二进制字符串。
  2. 逐位相加:从最低位开始,逐位相加,并处理进位。
  3. 处理进位:如果某一位的和大于等于2,则需要进位。
  4. 处理最高位进位:如果最后还有进位,需要将其添加到结果中。
  5. 反转结果:将结果反转回来,得到正确的二进制字符串。
  6. 转换为十进制:将最终的二进制字符串转换为十进制。
时间复杂度
  • 反转字符串:O(n)
  • 逐位相加:O(n)
  • 转换为十进制:O(n)

总的时间复杂度为O(n),满足题目要求。

总结

通过反转字符串、逐位相加并处理进位,最后将结果转换为十进制,可以有效地解决这个问题。希望这些思路对你有所帮助!


代码实现

def solution(binary1, binary2):
    
    # 反转字符串以便从最低位开始相加
    binary1 = binary1[::-1]
    binary2 = binary2[::-1]
    
    max_length = max(len(binary1), len(binary2))
    carry = 0
    result = []
    
    for i in range(max_length):
        bit1 = int(binary1[i]) if i < len(binary1) else 0
        bit2 = int(binary2[i]) if i < len(binary2) else 0
        
        # 计算当前位的和
        total = bit1 + bit2 + carry
        result.append(str(total % 2))  # 当前位的结果
        carry = total // 2  # 计算进位
    
    # 如果最后还有进位,添加到结果中
    if carry:
        result.append(str(carry))
    
    # 反转结果并转换为十进制
    result.reverse()
    decimal_result = str(int(''.join(result), 2))
    
    return decimal_result


if __name__ == "__main__":
    #  You can add more test cases here
    print(solution("101", "110") == "11")
    print(solution("111111", "10100") == "83")
    print(solution("111010101001001011", "100010101001") == "242420")
    print(solution("111010101001011", "10010101001") == "31220")

代码时间复杂度分析

时间复杂度的分析需要对python的一些特性比较了解

字符串切片的时间复杂度为O(k),其中k是切片的长度。这是因为字符串在内存中是连续存储的,所以切片操作只需要将起始位置指针向后移动k个位置,并复制k个字符到新的字符串中。需要注意的是,切片操作并不会改变原始字符串,而是创建一个新的字符串对象。

reverse函数的时间复杂度为O(n),其中n为可迭代对象中元素的个数。在处理大数据量时,需要注意reverse函数的性能影响。reverse函数是直接在原对象上进行修改,而不返回新的对象。这意味着在使用reverse函数时,原对象会被改变,可能会对后续的代码逻辑造成影响。

使用join()方法进行字符串连接的时间复杂度为O(n),其中n是连接的字符串的总长度。join()方法是通过一次性的拼接将多个字符串连接成为一个新的字符串,避免了每次拼接时都创建新的字符串对象的操作


Prompt

你帮我分析一下编辑区代码的时间复杂度

MarsCode AI

好的,让我们来分析一下你编辑区代码的时间复杂度。

代码分析
时间复杂度分析
  1. 反转字符串

    • binary1 = binary1[::-1] 和 binary2 = binary2[::-1] 的时间复杂度为 O(n),其中 n 是字符串的长度。
  2. 逐位相加

    • for i in range(max_length): 循环的时间复杂度为 O(n),其中 n 是两个字符串中较长的那个的长度。
    • 在循环中,每次操作的时间复杂度为 O(1)。
  3. 处理进位

    • if carry: 的时间复杂度为 O(1)。
  4. 反转结果

    • result.reverse() 的时间复杂度为 O(n)。
  5. 转换为十进制

    • int(''.join(result), 2) 的时间复杂度为 O(n)。
总时间复杂度
  • 反转字符串:O(n)
  • 逐位相加:O(n)
  • 处理进位:O(1)
  • 反转结果:O(n)
  • 转换为十进制:O(n)

总的时间复杂度为 O(n),其中 n 是两个字符串中较长的那个的长度。

结论

你的代码的时间复杂度为 O(n),满足题目要求的时间复杂度不超过 O(n^2) 的限制。 希望这些分析对你有所帮助!

代码优化

我们可以尝试让AI来帮我们进行代码优化

Prompt

给我一些代码提示

MarsCode AI

好的,让我们来提供一些代码提示,帮助你进一步优化和完善你的代码。

提示
  1. 代码优化

    • 你可以考虑使用zip_longest来简化逐位相加的逻辑。
    • 你可以使用bin函数来简化二进制字符串的转换。
  2. 错误处理

    • 你可以添加一些错误处理逻辑,例如检查输入是否为有效的二进制字符串。
  3. 测试用例

    • 你可以添加更多的测试用例,特别是边界情况,例如空字符串或非常大的二进制字符串。
示例代码
from itertools import zip_longest

def solution(binary1, binary2):
    # 反转字符串以便从最低位开始相加
    binary1 = binary1[::-1]
    binary2 = binary2[::-1]
    
    carry = 0
    result = []
    
    # 使用 zip_longest 逐位相加
    for bit1, bit2 in zip_longest(binary1, binary2, fillvalue='0'):
        bit1 = int(bit1)
        bit2 = int(bit2)
        
        # 计算当前位的和
        total = bit1 + bit2 + carry
        result.append(str(total % 2))  # 当前位的结果
        carry = total // 2  # 计算进位
    
    # 如果最后还有进位,添加到结果中
    if carry:
        result.append(str(carry))
    
    # 反转结果并转换为十进制
    result.reverse()
    decimal_result = str(int(''.join(result), 2))
    
    return decimal_result


if __name__ == "__main__":
    #  You can add more test cases here
    print(solution("101", "110") == "11")
    print(solution("111111", "10100") == "83")
    print(solution("111010101001001011", "100010101001") == "242420")
    print(solution("111010101001011", "10010101001") == "31220")
结果讨论

AI 用了 zip_longest 和 bin 进行优化,AI给出的示例代码可以通过测试

在Python的标准库itertools模块中,zip_longest函数是一个用于处理不等长可迭代对象的迭代器,与内置的zip函数相比,zip函数会以最短的可迭代对象为基准进行迭代,而zip_longest则以最长的可迭代对象为基准,使用fillvalue参数指定的值来填充较短的可迭代对象中缺失的元素。

for bit1, bit2 in zip_longest(binary1, binary2, fillvalue='0'):

zip_longest函数将这两个迭代器中的元素成对地组合在一起。 fillvalue='0'参数指定了当binary1或binary2中的一个迭代器先耗尽时,应该用什么值来填充。

关于这个题目

我不太清楚这道题目标为难题的难点所在,它对时间复杂度的要求并不高,而且对于长字符串的问题,python也可以比较方便的解决。或许是我没有意识到这一题的细节所在。

这道题的解决过程就是我和AI互相进步的过程,我和AI进行配合,AI帮助我完善思路,并进行复杂度分析,我则需要判断AI的说法是否满足我的需求,如果不够满足,则我需要重新提供一份更加完善的Prompt,以上就是我的所有工作内容。