此题是两个二进制字符串相加的问题,自己的版本到最后还有一点问题没有改好,而且不知为何输出总为空字符串,这会儿有点困,打算先参考一份跟自己思路比较一致的代码了。
题目:
Given two binary strings, return their sum (also a binary string).
The input strings are both non-empty and contains only characters 1
or 0
.
Example 1:
Input: a = "11", b = "1"
Output: "100"
Example 2:
Input: a = "1010", b = "1011"
Output: "10101"
要注意的问题有几个:
1.两个字符串长短不一,但都是从最后一位开始相加
2.相加时的进位问题,应该用经典的%个位/十位得到,除数为进制数2
3.在最短的字符串相加结束之后,后面的字符串并不是直接赋值,因为还是可能有最后一位的flag=1产生的影响
4.要考虑结束符的问题。假设a="111",则strlen(a)=3,不包括结束符'\0';相对的sizeof(a)=4,包括结束符'\0'
5.while(len--)是挺好用的,但while(len1--&&len2--)不能这样用,因为len2可能不被计算,Len1就被判断为0了
6.动态分配空间应该是strlen返回长度+1,因为还有结束字符。如果直接分配一个包含进位的空间也可以,那就是+2
7.int和char的转换没有那么神秘,int=char-‘0’ char=‘0’+int
先贴自己的第一版代码和明显的出错:
char* addBinary(char* a, char* b) {
int i,d,len,flag=0;
int len1=strlen(a);
int len2=strlen(b);
len=len1>len2?len1:len2;
char* result=(char*)malloc(len*sizeof(char));//空间至少len+1,应该考虑结束符
while(len1&&len2){
result[len-1]=a[len1-1]+b[len2-1]+flag;//忘记了数组中的元素是char而不是int,不能直接这样计算,下面也都出现了这个问题,不再标注了
if(result[len-1]>=2){
result[len-1]=result[len-1]-2;
flag=1;
}
else{flag=0;}
len1--;//这边是考虑了while(len1--&&len2--)不能用,因为len2可能不被计算,Len1就被判断为0了
len2--;//但是这里忘了同步把len--!!!
}
if(len1==len2&&flag==1){
(char*)realloc(result,(len+1)*sizeof(char));//这句还是没有考虑结束符,也不能len+2,因为len已经不是原来的len值了!
for(i=len;i>0;i--){//注意,之前len,len1,len2都在循环里被--了,这时的len并不是初始的len,不能这样用了!!
result[i]=result[i-1];
}
result[0]=1;//没有考虑最后一位结束符的赋值,而且没有注意是char类型
}
else{
if(len1){
while(len1--){result[len1-1]=a[len1-1];}//这边注意到了len和len1不同步,如果想都用的话,必须同步--;
}
if(len2){
while(len2--){result[len2-1]=a[len2-1];}
}
}
return result;
}
再贴自己的第二版代码(返回空字符串,不知道怎么改。。。):
char* addBinary(char* a, char* b) {
int i,c,d,e,f,len,flag=0;
int len1=strlen(a);
int len2=strlen(b);
len=len1>len2?len1:len2;
char* result=(char*)malloc((len+1)*sizeof(char));
result[len]='\0';
while(len1&&len2){
c=a[len1-1]-'0';
e=b[len2-1]-'0';
if(c+e+flag>=2){
result[len-1]='0'+c+e+flag-2;
flag=1;
}
else{flag=0;}
len1--;
len2--;
len--;
}
if(len1==len2&&flag==1){
f=strlen(a);
(char*)realloc(result,(f+2)*sizeof(char));
for(i=f;i>0;i--){
result[i]=result[i-1];
}
result[0]='1';
result[f+1]='\0';
}
else{
if(len1){
while(len1--){result[len1-1]=a[len1-1];}//这时不能直接赋值,还是有进位temp的影响!!!
}
if(len2){
while(len2--){result[len2-1]=a[len2-1];}//这时不能直接赋值,还是有进位temp的影响!!!
}
}
return result;
}
最后是参考的代码,这篇的思路跟自己的思路差不多,所以再修改的话就差不多也是这样了,参考链接:
https://blog.csdn.net/sanmao0816/article/details/45169097
/**
* 解题思路:另外申请一个数组用于保存相加后的二进制字符串,注意字转整型与整型转字符。注意二进制之间的进位。
*/
char *addBinary(char *a, char *b) {
int i,j, temp,temp1,lenA,lenB,len;
char *str;
lenA = strlen(a);
lenB = strlen(b);
len = lenA>lenB?lenA:lenB;
str= (char *)malloc((len+2)*sizeof(char));//申请的空间要大于最大的字符串长度加1+1,第一个1指字符串相加后可能进位,第二个1指字符串最后的'\0'结束字符
memset(str,0,(len+2)*sizeof(char));
//Memset 用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘/0’;
例:char a[100];memset(a, '/0', sizeof(a)); memset可以方便的清空一个结构类型的变量或数组。
j = len-1;temp = 0;
for(i=len;i >= 0 && lenA > 0 && lenB > 0; i--){
*(str+i) = ((*(a+lenA-1)-'0') + (*(b+lenB-1)-'0') + temp)%2 + '0';// 该位取%
temp = ((*(a+lenA-1)-'0') + (*(b+lenB-1)-'0') + temp)/2;// 进位取/
lenA--;lenB--;
}
if(lenA == 0){//判断谁先结束了,lenA == 0则A先结束,将b字符串赋值给str
for(; lenB > 0;i--){
*(str+i) = ((*(b+lenB-1)-'0') +temp)%2 + '0';//这时不是直接赋值,还是有进位temp的影响!!!
temp = ((*(b+lenB-1)-'0') +temp)/2;
lenB--;
}
}else if(lenB == 0){//b先结束了,则把a字符串赋值给str
for(; lenA >0;i--){//这里的i还是用之前的值作为初始值;
*(str+i) = ((*(a+lenA-1)-'0') + temp)%2+'0';
temp = ((*(a+lenA-1)-'0') + temp)/2;
lenA--;
}
}
if(temp == 1) {*(str+i) = temp+'0';return str+i;}//若temp进位为1,则赋值给str[i],返回最高位的地址str+i
return str+i+1;//没有进位的话,返回最高位地址str+i+1;
//这个代码没有重新根据情况分配内存空间,所以最高位不一定是str[0]还是str[1];所以返回的时候不能单一的返回。
}
java思路有两种,一种是先将两个字符串逐位从右到左相加的和与进位相加,放入字符数组中。最后等到短的字符串加完之后,留下较长的为加完毕字符串和进位,用以补充字符数组。当然这种解法比较麻烦;另一种是将最短的字符串右端用0补齐,这时两个字符串就等长了,这样就可以逐位相加,最后还有判断是否有进位,如果有进位还得在最左端补上一位1。
以下是思路2的过程代码:
public class Solution {
public String addBinary(String a, String b) {
int aLen = a.length();
int bLen = b.length();
if(aLen > bLen){//如果字符串a的长度较长
int gap = aLen - bLen;
while(gap>0){
b = 0 + b;//整数+字符串可以直接得到添加了整数元素的字符串,每次都加前面
gap--;
}
}//用0补齐较短的字符串,至两字符串a、b等长
if(bLen > aLen) {
int gap = bLen - aLen;
while(gap>0){
a = 0 + a;
gap--;
}
}
int maxLen = aLen > bLen ? aLen : bLen;
int c = 0, sum = 0;
String result = "";//注意字符串的声明要首字符大写
for(int i = maxLen-1; i >= 0; i--) {
sum = a.charAt(i)+b.charAt(i)-'0'*2+c;//字符串可以直接以.charAt(i)定位符号,不用非转化成字符型数组char[];字符减字符等于整数,比如'1'-'0'=1,后面以数值判断状态,而不是符号。
if(sum > 1) {
c = 1;
sum -= 2;
} else {
c = 0;
}
result = sum + result;//整数+字符串可以直接得到添加了整数元素的字符串
}
if(c == 1) result = 1 + result;//考虑最后如果还存在进位
return result;
}
}