AI刷题总结与反思——其二|豆包MarsCode AI刷题

60 阅读6分钟

本系列将分享十一月在marscode上遇到的比较有意思的题目供同学们交流分享。

————本题具有一定挑战性,请看passage:

问题描述

小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过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'

继模块化思想依然进行模块化设计:

模块 1:binaryAddition 函数

int binaryToDecimal(int *binary_result, int len) {
    int decimal_result = 0;
    for (int i = len - 1; i >= 0; i--) {
        decimal_result += binary_result[i] * (1 << (len - 1 - i));
    }
    return decimal_result;
}
  • 功能:该函数接受两个二进制字符串 binary_str1 和 binary_str2,以及一个用于存储相加结果的整数数组 result,负责将两个二进制字符串逐位相加,并把结果存储在 result 数组中。

  • 输入参数

    • const char *binary_str1:第一个二进制字符串,通过指针传入,函数内部不会修改其内容,保证了输入数据的安全性。
    • const char *binary_str2:第二个二进制字符串,同理也是只读传入。
    • int *result:指向整数数组的指针,用于存储相加后的二进制结果,调用函数前需确保该数组有足够空间(在 main 函数中按规则分配了内存)。
  • 内部变量及作用

    • int len1 和 int len2:分别存储两个二进制字符串的长度,通过 strlen 函数获取,用于后续确定处理边界和结果数组长度。
    • int max_len:存储两个字符串长度中的较大值,以便确定结果数组最终需要覆盖的有效长度范围,考虑到进位情况结果数组长度设为 max_len + 1
    • int ptr1 和 int ptr2:分别作为指向两个二进制字符串末尾(最低位)的指针,随着相加过程逐步往前移动,以便按位处理相加操作。
    • int carry:进位变量,初始化为 0,在每一位相加时,若两数和大于等于 2 就产生进位,该变量记录进位值以便下一位相加时一并处理。
    • int idx:用于指示结果数组 result 中存储当前相加结果位的索引,从 0 开始随着循环递增。
  • 核心逻辑

    • 进入循环,只要两个字符串还有未处理位(ptr1 >= 0 或 ptr2 >= 0)或者还有进位(carry!= 0),就持续执行以下步骤:

      • 通过判断 ptr1 和 ptr2 是否大于等于 0,获取对应位的值(将字符 '0' 或 '1' 转换为整数值 0 或 1)并累加到 sum 变量,同时加上进位 carry
      • 计算新的进位 carry,将 sum 除以 2 取整,更新进位值。
      • 把 sum 对 2 取余的结果存入 result 数组对应索引 idx 位置,完成当前位结果存储。
      • 移动 ptr1ptr2 和 idx,准备处理下一位。循环结束后,若最后还有进位,将其存入结果数组最高位 result[max_len]

模块 2:binaryToDecimal 函数

void binaryAddition(const char *binary_str1, const char *binary_str2, int *result) {
    int len1 = strlen(binary_str1);
    int len2 = strlen(binary_str2);
    int max_len = len1 > len2? len1 : len2;
    int ptr1 = len1 - 1;
    int ptr2 = len2 - 1;
    int carry = 0;
    int idx = 0;

    while (ptr1 >= 0 || ptr2 >= 0 || carry!= 0) {
        int sum = 0;
        if (ptr1 >= 0) {
            sum += binary_str1[ptr1] - '0';
        }
        if (ptr2 >= 0) {
            sum += binary_str2[ptr2] - '0';
        }
        sum += carry;

        carry = sum / 2;
        result[idx] = sum % 2;

        ptr1--;
        ptr2--;
        idx++;
    }

    if (carry!= 0) {
        result[max_len] = carry;
    }
}
  • 功能:此函数将一个用整数数组表示的二进制结果转换为十进制数并返回。

  • 输入参数

    • int *binary_result:指向存储二进制结果的整数数组的指针,该数组按二进制位顺序存储,最高位在前(索引大的位置),最低位在后。
    • int len:输入二进制数组的长度,用于确定位权展开的次数和范围。
  • 内部变量及作用

    • int decimal_result:用于累加计算最终十进制结果的变量,初始化为 0,随着循环按位权展开法逐步更新,最终存储完整的十进制转换结果。
  • 核心逻辑

    • 从二进制数组的最高位(索引 len - 1)开始循环到最低位(索引 0),对于每一位 binary_result[i],将其乘以 2 的对应幂次(幂次为 len - 1 - i,根据位权规则确定),并累加到 decimal_result 变量中,循环结束后 decimal_result 即为转换后的十进制数。

主函数结构

int main() {
    const char *binary_str1 = "1010";
    const char *binary_str2 = "1101";
    int max_len = strlen(binary_str1) > strlen(binary_str2)? strlen(binary_str1) : strlen(binary_str2);
    int result_len = max_len + 1;
    int *result = (int *)malloc(result_len * sizeof(int));
    if (result == NULL) {
        printf("内存分配失败!\n");
        return -1;
    }
    for (int i = 0; i < result_len; i++) {
        result[i] = 0;
    }

    binaryAddition(binary_str1, binary_str2, result);
    int decimal_sum = binaryToDecimal(result, result_len);
    printf("两个二进制字符串相加的十进制结果为:%d\n", decimal_sum);

    free(result);
    return 0;
}

核心逻辑

  • 首先分配 result 数组内存,初始化数组元素为 0。

  • 调用 binaryAddition 函数,传入两个二进制字符串和 result 数组,完成二进制相加并存入 result 数组。

  • 调用 binaryToDecimal 函数,传入 result 数组及其长度,获取十进制转换结果并存储到 decimal_sum 变量。

  • 输出 decimal_sum,展示最终相加结果的十进制形式,最后释放 result 数组内存,结束程序

总而言之,本题有较强的逻辑性,需要一定的结构方案、算法设计来减少错误产生。

而这种模块化设计使得代码逻辑更清晰,每个模块各司其职,易于理解、调试与维护,若后续要修改二进制相加规则或者转换算法,可针对性在对应模块内进行操作,减少对整体代码的影响范围。

思维强度较高的题目其实也往往具有较高的学习、研究价值,不容错过。