原题链接:https://leetcode.com/problems/add-binary/
1. 题目介绍
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.
给出两个字符串,都表示二进制的数。保证这两个数都是非零的,并且每个位都只能是0或者1.
求这两个二进制数的和,当然求出的和也要用二进制表示。
Example 1:
Input: a = "11", b = "1"
Output: "100"
Example 2:
Input: a = "1010", b = "1011"
Output: "10101"
2. 解题思路
2.1 使用堆栈
这是我想到的第一个方法,将两数放到堆栈中,然后再一位一位弹出、相加。这个方法并不是最好的方法,速度也较慢。
实现代码
class Solution {
public String addBinary(String a, String b) {
Stack<Integer> sta = StringToStack(a);
Stack<Integer> stb = StringToStack(b);
Stack<Integer> ans = new Stack<Integer> ();
int carry = 0;
while(sta.empty() == false || stb.empty() == false){
int na = (sta.empty() == false ? sta.pop() : 0);
int nb = (stb.empty() == false ? stb.pop() : 0);
int k = na + nb + carry;
carry = k/2;
ans.push(k%2);
}
if(carry != 0){
ans.push(carry);
}
StringBuffer buf = new StringBuffer();
while(ans.empty() == false){
buf.append( ans.pop() );
}
String ansString = buf.toString();
return ansString;
}
public Stack<Integer> StringToStack(String s){
Stack<Integer> st = new Stack<Integer> ();
for(int i = 0 ; i < s.length() ; i++){
st.push(s.charAt(i) - '0');
}
return st;
}
}
特别提醒:字符串一旦定义则不可改变
字符串一旦定义则不可改变,请看下面代码:
String str = "hello"; //此时字符串str是hello
str = str + "world";//此时字符串是helloworld
上面的程序首先声明了一个String类的对象,然后修改了String类对象的内容。但是第二行代码对字符串的修改实际上是引用的改变。因为str引用和字符串的实际内容并不是存放在一个空间里的。str存放在栈内存,字符串的内容存放在堆内存。
一开始,栈内存的str指向了堆内存的“hello”。因为字符串一旦定义则不可改变,执行第二行语句 str = str + “world”; 时,并不是简单地在hello后面新加一个world,而是在堆内存重新开辟了一个空间存放“helloworld”,然后让str指向新的“helloworld”。原来的“hello”并没有什么变化,仅仅是没有引用指向它了而已,最终没有引用的“hello”将成为垃圾空间。
正因为这样的特性,在程序中应该尽量回避频繁改变字符串的操作,比如:
String str = "";
for(int i = 0 ; i < 100 ; i++){
str += i;
}
但是,如果确实遇到需要对字符串进行频繁修改的情况该怎么办?可以考虑用StringBuilder 或者StringBuffer 类代替。
下面以StringBuffer为例:
StringBuffer buf = new StringBuffer();
buf.append("hello"); //append方法可以进行数据追加操作
System.out.println(buf);//输出hello
buf.append("world");
System.out.println(buf);//输出helloworld
buf.append(123);
System.out.println(buf);//输出helloworld123
String str = buf.toString();//toString 方法可以将StringBuffer转化为String类
System.out.println(buf);//输出helloworld123
2.2 直接从后向前扫描字符串
使用StringBuffer对频繁修改字符串,避免了使用String产生过多垃圾内存的弊端。从两个字符串后面扫描字符串。将两个字符串的数和进位相加,产生新的进位,进位完成后,再将余下的一位并入结果字符串。
实现代码
class Solution {
public String addBinary(String a, String b) {
int ia = a.length()-1;
int ib = b.length()-1;
int carry = 0;
StringBuffer buf = new StringBuffer();
while(ia >= 0 || ib >= 0){
int na = (ia >=0 ? (a.charAt(ia--) == '0' ? 0 :1 ) : 0);
int nb = (ib >=0 ? (b.charAt(ib--) == '0' ? 0 :1 ) : 0);
int k = na + nb + carry;
carry = k/2;
buf.append( k%2 );
}
if(carry != 0){
buf.append( carry );
}
String ansString = buf.reverse().toString();
return ansString;
}
}