LeetCode算法题目之Add Binary 我的思路

问题的链接:https://leetcode.com/problems/add-binary/

Given two binary strings, return their sum (also a binary string).

For example,
a = "11"
b = "1"
Return "100".

<pre name="code" class="html">刚刚看到题目想要使用刚刚学习的bitset进行操作。
 

写好以后要做加法的时候发现bitset只是表示bit的一种结构,并不能完成二进制的数学运算。只有所谓的int类型可以完成运算,只不过常规的表示形式是十进制,但可以使用printf进行格式化输出。不过将其转化成一个字符串的表示形式还要需要数学上的运算,也就是将每一位的数字提取出来,对于做过十进制除法提取数字的程序的人来说并不算难。根据每个位上的数字来构建字符串。姑且叫作思路一。

还有一种思路就是源于好在二进制的运算比较简单。可以直接提取每一个string的位,并模拟二进制运算规则来生成新的字符串。那么我需要一个用来存储结果的resultString和用来存储进位的flagString。然后使用二进制运算规则来进行置位。这个叫做思路二。

当然,字符串最后需要进行一下处理,就是要把前面空白的“0”给去掉,从第一位开始设定有效数字。

这里在编码过程中有一些小用法。C++的string类可以直接使用“+”operator进行拼接。char*类型才需要用一些str开头的函数操作。

下面是代码:

class Solution {
public:
//获取并输入大小并动态分配字符串。进位保存串和结果串,结果的位数只可能比位数最大的加数大一位,所以分配为i+位。
int getMaxbitsNum(string a,string b){
if(a.size()>=b.size()){
return a.size();
}else{
return b.size();
}
}
string * getNewString(int num){
string* pStr=new string(num,'0');//分配num个0
return pStr;
}
//get位数函数,get数字的位数
int getBit(string a,int max,int i){//传递字符串应该是穿的引用
int length=max;
//输入复合要求
if(a[length-i]=='1'){
return 1;
}
else{return 0;}



}
void setBit(string & a,int max,int i){
int length=max;

a[length-i]='1';

}
int charToInt(char a){//判断char型转换成int
if(a=='1'){return 1;}
else{return 0;}
}
/*void alignBack(int max,string * oriStr){
int dif=max+1-(*oriStr).size();
string *a=getNewString(dif);
oriStr=(*a)+


}*/
string add(string a,string b){
int max=getMaxbitsNum(a,b);
string *flagStr=getNewString(max+1);
string *sumStr=getNewString(max+1);
//复制对齐较短的字符串
string *adif=getNewString(max+1-a.size());
string *bdif=getNewString(max+1-b.size());
a=(*adif)+a;
b=(*bdif)+b;

for(int i=1;i<=max+1;i++){//模仿一位全加器
int flag=getBit(a,max+1,i)+getBit(b,max+1,i)+getBit(*flagStr,max+1,i);
switch(flag){
case 3: 
setBit(*sumStr,max+1,i); 
setBit(*flagStr,max+1,i+1);
break;
case 2 :
setBit(*flagStr,max+1,i+1);
break;
case 1:
setBit(*sumStr,max+1,i);
break;
case 0:
break;
}
}
if((*sumStr)[0]=='0'){//若字符串第一位为0则从第二位开始复制到另一个里面,否则直接返回
string *newString=new string(max,'0');
(*newString).assign((*sumStr),1,string::npos);//将第零位截断
return *newString;
}else{
return *sumStr;
}
}
//相加函数:获取maxbit,分配两个maxbit+1长度字符串,
    string addBinary(string a, string b) {
       return add(a,b);
      
    }
};

可以直观感受一下代码有些长,有了83行,不过好在所有的测试用例都通过了。不过在C++代码的速率当中只打败了4%。还要多多学习啊。


接下来我要看看其他大神的一两行的算法了。好激动。

【一个很重要感想】

因为刚一开始对string的成员函数的掌握并不多,不知道可以直接+拼接。使得从刚一开始的整体规划就有所偏颇。

还有就是在进行编码之前,你的思路一定要足够明确,细节要可行。否则等待开始编码的时候再进行修改就会很困难。

我的运行时间是8ms,下面是一个网站上的一个4ms的算法。都是构造全加器,我是直接case字符是‘0’或‘1’进行判断,这位高人是将字符转化为bool直接使用“^”异或运算符和“?”判断,十分简洁。

for(i=maxlen-1;i>=0;i--)  

{ret=(char)(((a[i]-'0')^(b[i]-'0')^sig)+48)+ret;  

((a[i]-'0')+(b[i]-'0')+sig)>=2?sig=1:sig=0;}

开始的时候测量字符串长度,然后使用+“ ”进行补全统一。

利用“-‘0’”结构将某一位的字符转化为int,再在异或运算符前面默认为bool数值(因为只可能为0或1),加数被加数和进位进行异或得到本位。再+48还原回字符。最后拼接上ret(初始为空字符)。

在求int的进位和加数和确定是否进位。

直接使用内置类型的运算,极大的节约了运算时间和空间。

再来看一个简洁的C++代码:

for (int i = a.size() - 1, j = b.size() - 1; i >= 0 || j >= 0; i--, j--) {

int m = (i >= 0 && a[i] == '1');  

int n = (j >= 0 && b[j] == '1');  

ret = to_string((m + n + carry) & 0x1) + ret;  

carry = (m + n + carry) >> 1;  

}  

return carry ? '1' + ret : ret;

使用了&0x1运算来提取出最后一位的值。

同时用加和左移来提取进位位。

【感受,了解足够多的运算符可以多很多思路】

网站上还有两行的 python语言实现的。我还不会,不过更高效的语言的效率我算是见识了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马工匠坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值