二进制之和、魔法甜点之和 | 豆包MarsCode AI刷题

82 阅读4分钟

选取了选择豆包MarsCode AI 刷题题库中的两道困难题目进行解析:二进制之和、魔法甜点之和:小包的新挑战。

二进制之和

问题描述

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

思路分析

  • 数据结构选择:由于我们处理的是字符串形式的二进制数,我们可以直接操作字符串,而不需要将其转换为整数类型。这样可以避免整数溢出的问题。
  • 算法步骤:
  1. 补齐长度:确保两个二进制字符串的长度相同。如果长度不同,可以在较短的字符串前面补0。这里使用zfill()方法,在字符串的左端补0。
  2. 逐位相加:从最低位(字符串的最后一位)开始,逐位相加,并记录进位。
  3. 处理进位:在每一位相加时,如果结果大于1,则需要进位。
  4. 生成结果:将每一位的结果(包括进位)拼接起来,形成最终的二进制字符串。
  5. 转换为十进制:最后,将二进制字符串转换为十进制字符串。

代码实现

def solution(binary1, binary2):
    # 补齐长度
    max_len = max(len(binary1), len(binary2))
    binary1 = binary1.zfill(max_len)
    binary2 = binary2.zfill(max_len)
    
    carry = 0
    result = []
    
    # 从最低位开始逐位相加
    for i in range(max_len - 1, -1, -1):
        bit1 = int(binary1[i])
        bit2 = int(binary2[i])
        sum_bit = bit1 + bit2 + carry
        
        # 计算当前位的结果和进位
        result.append(str(sum_bit % 2))
        carry = sum_bit // 2
    
    # 如果最高位有进位,需要额外添加一位
    if carry:
        result.append('1')
    
    # 结果是反向的,需要反转
    result.reverse()
    
    # 将二进制结果转换为十进制
    binary_result = ''.join(result)
    decimal_result = str(int(binary_result, 2))
    
    return decimal_result

学习总结

zfill(len)方法,在左边填充0直至填充字符串长度为len;

反向遍历数组的方式:for i in range(n, -1, -1);

//整除,python的整除是地板除法,向下取整;

int(string, base)可以将base进制的字符串转换成10进制整数。

魔法甜点之和:小包的新挑战

问题描述

小R不再追求甜点中最高的喜爱值,今天他想要的是甜点喜爱值之和正好匹配他的预期值 S。为了达到这个目标,他可以使用魔法棒来改变甜点的喜爱值,使其变为原来喜爱值的阶乘。每个甜点只能使用一次魔法棒,也可以完全不用。

下午茶小哥今天带来了 N 个甜点,每个甜点都有一个固定的喜爱值。小R有 M 个魔法棒,他可以选择任意甜点使用,但每个甜点只能使用一次魔法棒。他的目标是通过选择一些甜点,可能使用魔法棒,使得这些甜点的喜爱值之和恰好为 S

请计算小R有多少种不同的方案满足他的要求。如果两种方案中,选择的甜点不同,或者使用魔法棒的甜点不同,则视为不同的方案。

思路分析

参考了csdn上的博文:blog.csdn.net/2301_788484…

对于数组like中任意一个元素,有四种选择:选择,不选,用魔法棒选,用魔法棒不选。结合题目情景,没有用了魔法棒但不选的情况,所以只有三种方式。使用深度优先搜索DFS算法,遍历得出所有方案。

退出DFS的条件:当满足条件返回;所有元素遍历完返回;所选value>s返回。

代码解释:

  • 参数

    • i:当前处理的甜点索引。
    • n:甜点的总数。
    • m:剩余可用的魔法棒数量。
    • s:目标喜爱值之和。
    • like:甜点的喜爱值列表。
  • 递归终止条件

    • 当 s == 0 且 m >= 0 且 i <= n 时,表示找到了一个满足条件的方案,sum 加 1。
    • 当 s < 0 或 m < 0 或 i == n 时,表示当前路径不可行,直接返回。
  • 递归调用

    • dfs(i + 1, n, m, s - like[i], like):不使用魔法棒,但选择当前甜点。
    • dfs(i + 1, n, m, s, like):不使用魔法棒,也不选择当前甜点。
    • dfs(i + 1, n, m - 1, s - factorial(like[i]), like):使用魔法棒,选择当前甜点。

代码实现

def factorial(x):
    i=0
    sum=1
    for i in range(1, x+1):
        sum*=i

    return sum

def dfs(i, n, m, s, like):
    global sum
    if s==0 and m>=0 and i<=n:
        sum+=1
        return

    if s<0:
        return
 
    if m<0:
        return
 
    if i==n:
        return

    dfs(i+1, n, m, s-like[i], like) # 不用但选
    dfs(i+1, n, m, s, like) # 不用不选
    dfs(i+1, n, m-1, s-factorial(like[i]), like) #用选


def solution(n, m, s, like):
    global sum
    sum = 0
    dfs(0, n, m, s, like)
    return sum

学习总结

方案寻找类问题可采用回溯法,使用DFS等遍历算法;巧用全局变量。