力扣:二进制求和(详解)

前言:内容包括:题目,代码实现,大致思路,代码解读

题目:

给你两个二进制字符串 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个空间

力扣:二进制求和(详解)_第1张图片

力扣:二进制求和(详解)_第2张图片

力扣:二进制求和(详解)_第3张图片

代码解读: 

 part 1

    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--,找到从后往前第一个要被存放字符的空间

part 4

    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

你可能感兴趣的:(leetcode,c语言)