前言:内容包括:题目,代码实现,大致思路,代码解读
给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。
示例 1:
输入:a = "11", b = "1"
输出:"100"
示例 2:
输入:a = "1010", b = "1011"
输出:"10101"
char * addBinary(char * a, char * b)
{
int lena = strlen(a);
int lenb = strlen(b);
int len = lena>lenb?lena:lenb;//最长字符串的长度
char*ret = (char*)malloc(sizeof(char)*(len+2));
if(ret==NULL)
{
return ;
}
int k = len+1;
ret[k--] = '\0';
int i = lena-1;
int j = lenb-1;
int carry = 0;
while(i>=0 || j>=0 || carry)
{
carry+=i>=0?a[i--]-'0':0;
carry+=j>=0?b[j--]-'0':0;
ret[k--] = carry%2+'0';
carry/=2;
}
return ret+k+1;
}
相加会存在进位与不进位的问题:
不进位:相加的结果转成字符串,它的长度是最长字符串的长度
“11”+“0” ->"11"
进位:相加的结果转成字符串,它的长度是最长字符串的长度+1
“11”+“1”->"100"
所以我们按照进位的情况来考虑,malloc动态开辟一块大小为最长字符串长度+2的空间
因为考虑进位得到的相加结果是最长字符串长度+1,还需要多出一个空间来存储'\0'
因为要返回的是字符串
1 将动态开辟的一块空间的最后一个空间置为'0'
2 两个字符串都从后往前遍历,让对应位置上的a字符串和b字符串的数字字符所对应的数值相加
a 将其相加结果%2得到的值转成对应的数字字符形式存入动态开辟的空间中
b 相加结果/2得到进位的值
3 只要a和b字符串中有任意一方还未遍历完,相加的动作还是继续
只要进位的值不为0,相加的动作也还是继续
4 由于存在进位与不进位的两种情况,我们按照了进位的情况来开辟了空间
实际上,当两串字符串相加却无需进位时,我们的空间是开辟多了的,则我们不能直接返回动态开辟空间的起始地址,因为我们是从后向前存储字符的,不进位时,空间不会被填满,所以我们需要找到真正的要被返回字符串的起始地址
当存完相加结果的最后一个字符时,由于k--是后置--,则k+1才是被返回字符串的起始地址
进位版:开辟len+2个空间
int lena = strlen(a);
int lenb = strlen(b);
int len = lena>lenb?lena:lenb;
比较字符串a和字符串b的长度,找出二者中的较长者(两字符串相加结果的至少长度)
part 2
char*ret = (char*)malloc(sizeof(char)*(len+2));
if(ret==NULL) //开辟空间失败
{
return ;
}
malloc动态开辟len+2个空间,因为存在进位的可能,则两字符串相加结果为len+1,还需多出一个空间存放\0,故而开辟len+2个空间
part 3
int k = len+1;
ret[k--] = '\0';
k是开辟的一块连续空间的最后一个空间的下标,我们需要将其值置为\0,即字符串的结束标志
然后k--,找到从后往前第一个要被存放字符的空间
int i = lena-1;//字符串a最后一个字符的下标
int j = lenb-1;//字符串b最后一个字符的下标
int carry = 0; //存储两个数值相加的结果
while(i>=0 || j>=0 || carry)
{
carry+=i>=0?a[i--]-'0':0;
carry+=j>=0?b[j--]-'0':0;
ret[k--] = carry%2+'0';
carry/=2;//进位的值
}
只要字符串a和字符串b中有任意一方还未遍历完,就可以执行相加的动作:carry+=
注意:字符串a和字符串b中的每个元素都是字符,数字字符是不可以直接进行运算的,需要将其转成对应的数值,才可参加运算
数字字符-'0' =数字
'3'-'0' = 3