上記のアルゴリズムの問題をリートコードします:(https://leetcode-cn.com/problems/add-binary/)
2つのバイナリ文字列が与えられた場合、それらの合計を(バイナリ表現で)返します。
入力は空ではない文字列であり、数値1と0のみが含まれています。
例1:
入力:a = "11"、b = "1"
出力: "100"
例2:入力:a = "1010"、b = "1011"
出力: "10101"ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/add-binary
調査すべき主な知識ポイント:
1.現在の文字のASCII値から「0」のASCII値を引いたものは、この文字を数値に変換することと同じです。
2. 違いStringBuilder
StringBuffer
3.文字反転reverse();のメソッド。
4.時間計算量の計算
実装のアイデア:
全体的な考え方は、短い方の2つの文字列に00を入力して、2つの文字列を同じ長さにし、計算を最後からトラバースして最終結果を取得することです。
この質問の解決策の一般的な考え方は上記と同じですが、文字列操作の理由により、最終結果にもう1つのキャリーがあるかどうかは不明であるため、2つの方法で対処できます。
最初のタイプは、計算中に文字列を直接連結することで、逆文字を取得します。
これは、最後に逆にする必要があります。2番目のタイプは、位置に応じて結果文字を割り当て、最後にキャリーがある場合です。 、キャリーを追加するために文字列が前に接続されます
オプション1:関連コード(psアスキーの知識ポイントは盲点であるため、アイデアを書いて理解し、コメントを追加しながら、文ごとに入力しました)
class Solution {
public String addBinary(String a, String b) {
int aLen = a.length();
int bLen = b.length();
int maxLen = Math.max(aLen,bLen);
//字符串进行翻转
StringBuilder sbA = new StringBuilder(a).reverse();
StringBuilder sbB = new StringBuilder(b).reverse();
//让两个字符串补齐成一个长度,翻转过后前置位补0
while(sbA.length() < maxLen){
sbA.append("0");
}
while(sbB.length() < maxLen){
sbB.append("0");
}
StringBuilder res = new StringBuilder();
//进位的标志位, 默认是0
int carry = 0;
//知识点:当前字符的 ASCII 值减去 '0' 的 ASCII 值,相当于将这个字符转换成数值
int num1;
int num2;
for(int i=0; i < maxLen; i++){
num1 = sbA.charAt(i) - '0';
num2 = sbB.charAt(i) - '0';
if(carry + num1 + num2 > 1){
//1+1的情况,在二进制下 需要减去2
res.append(carry + num1 + num2 - 2);
//表示 需要进位,改变标志位
carry = 1;
}else{
res.append(carry + num1 + num2);
carry = 0;
}
}
//对于最高位 需要增加位数,如果存在进位的情况
if(carry == 1){
res.append("1");
}
//最后再翻转一次,为开始补位的时候就是翻转后的
return res.reverse().toString();
}
}
オプション2:関連コード(psを文ごとに入力し、書きながらアイデアを理解し、コメントを追加します)
上記のコードは2回「反転」されますが、これは少し冗長です。2つのポインターを使用して文字列の末尾から前方にトラバースすると同時に、StringBuilderオブジェクトの挿入メソッドを借用して計算結果を右から取得できます。左へ。、手作業による「垂直加算」のプロセスに非常に近いです。以下はリファレンスコードです(ソリューションから抜粋)
private String doAddWithInsert(String a, String b){
int i = a.length() - 1;
int j = b.length() - 1;
//这个是结果: 可变的字符序列对象
StringBuilder res = new StringBuilder();
int curSum;
//进位的标志位
int carry = 0;
while(i >=0 || j >=0){
curSum = carry;
//当前位置的a的i位和 b 的j 位,都是末位进行相加
if(i >= 0){
curSum += a.charAt(i) - '0';
i--;
}
if(j >= 0){
curSum += b.charAt(j) - '0';
j--;
}
//判断是否需要进位
if(curSum > 1){
//1+1的情况,在二进制下 需要减去2,有进位
curSum -= 2;
carry = 1;
}else{
carry = 0;
}
// 只写结果的值,进位作为下一轮的初始值
res.insert(0, curSum);
}
if(carry == 1){
res.insert(0, 1);
}
return res.toString();
}
解決策1の方が理解しやすいかもしれませんが、解決策2は、垂直加算の考え方に沿ったものです。主なポイントは、インサートの使用です。