本系列将分享十一月在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位置,完成当前位结果存储。 - 移动
ptr1、ptr2和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数组内存,结束程序
总而言之,本题有较强的逻辑性,需要一定的结构方案、算法设计来减少错误产生。
而这种模块化设计使得代码逻辑更清晰,每个模块各司其职,易于理解、调试与维护,若后续要修改二进制相加规则或者转换算法,可针对性在对应模块内进行操作,减少对整体代码的影响范围。
思维强度较高的题目其实也往往具有较高的学习、研究价值,不容错过。