目录
一、题目描述
二、初次解答
三、官方解法
四、总结
一、题目描述
二、初次解答
1. 思路:将a和b两个字符串转换成十进制,然后将相加的结果转换回文本的二进制。
2. 代码:
char* addBinary(char* a, char* b) { int a_len = strlen(a); int b_len = strlen(b); //将a和b的二进制转换为int十进制 int value[2] = {0, 1}; int aRet = 0, bRet = 0; for (int i = a_len - 1; i >= 0; --i) { aRet += value[a[i] - '0'] * pow(2, a_len - 1 - i); } for (int j = b_len - 1; j >= 0; --j) { bRet += value[b[j] - '0'] * pow(2, b_len - 1 - j); } //计算十进制之和,将结果转换为二进制并保存 int Ret = aRet + bRet; if (Ret == 0) { return a; } int lenMax = (a_len > b_len)?a_len:b_len; char* ret = (char*)malloc(sizeof(char) * (lenMax + 2)); ret[lenMax + 1] = '\0'; char valuec[2] = {'0', '1'}; int k = lenMax; for (; Ret != 0; --k) { ret[k] = valuec[Ret % 2]; Ret /= 2; } if (k >= 0){ return ret + 1; } return ret; }
3. 缺陷:对于相加超过int范围的例子,就无法求解!
三、官方解法
1. 思路:将两个字符串反转,然后存放至目标数组的元素值为(a[i]+b[i]+进位值)%2,而进位值为(a[i]+b[i]+进位值)/2。最后,将目标数组再次反转即可。
2. 代码:
void reverse(char* s) { int len = strlen(s); for (int i = 0, j = len - 1; i < j; i++, j--){ char temp = s[i]; s[i] = s[j]; s[j] = temp; } } char* addBinary(char* a, char* b) { reverse(a); reverse(b); int a_len = strlen(a), b_len = strlen(b); int lenMax = (a_len > b_len)?a_len:b_len; char* ret = (char*)malloc(sizeof(char) * (lenMax + 2)); int flag = 0, len = 0; for (int i = 0; i < lenMax; ++i){ flag += i < a_len ? (a[i] == '1') : 0; flag += i < b_len ? (b[i] == '1') : 0; ret[len++] = flag % 2 + '0'; flag /= 2; } if (flag == 1){ ret[len++] = '1'; } ret[len] = '\0'; reverse(ret); return ret; return a; }
3. 优点:实现思想较为简单。
4. 缺点:①使用了三次反转,执行时间较长。②核心for循环中的语句很难想到这么精简的。
四、总结
当遇到反向操作时,可以尝试使用三次反转来完成。另外,对于位数不齐的情况,可以使用三元运算符来综合有位数和无位数的情况。例如,flag += i < a_len ? (a[i] == '1) : 0;就是先判定i是不是小于a的长度,如果是才进行访问,否则直接给0,避免了越界访问的错误。