この問題はJava-> C#変換ではなく、文字列をStringBuilderに変換したという事実にあります。あなたはあなたが追加されている
str.Append("(");
を呼び出すと、「(」現在の文字列ビルダインスタンス(str
)、そしてあなたが
CombiParentheses(open - 1, close + 1, str.Append("("));
にを渡すあなたのメソッド呼び出しでインスタンス自体、ないこと新しいインスタンス
問題を確認する簡単な方法は:あなたが
CombiParentheses(2, 0, str);
を呼び出していると仮定します
第二の出力文字列が書き込まれると、あなたは、単一の文字列ビルダのインスタンスを使用している、とあなたは、コールスタックが
CombiParentheses(1, 0, str.Append(")"));
に入った右の前にそれをクリアしているので、コールスタックが
CombiParentheses(2, 0, str):
CombiParentheses(1, 1, str.Append("(")):
CombiParentheses(0, 2, str.Append("(")):
CombiParentheses(0, 1, str.Append(")")):
CombiParentheses(0, 0, str.Append(")")); // StringBuilder was reset here!
CombiParentheses(1, 0, str.Append(")")):
CombiParentheses(0, 1, str.Append("(")):
CombiParentheses(0, 0, str.Append(")"));
ていただろう
次の出力は、strに文字がありませんでしたが、のように出力されます(strにはまだ"("
が残っているかのようです)。あなたの代わりに文字列を使用した場合、あなたが(string + ")")
行うとき
は、結果が新しい文字列ではなく、あなたが変更され、同じオブジェクトであるので、あなたが作ったCombiParentheses
コールに戻って取得するときに問題が発生しません以前の再帰実行では、まだCombiParentheses
呼び出しが受信された元の文字列があります。
あなたは、実行時にそれを見ていますこれを使用することができます:
public static void CombiParentheses(int open, int close, StringBuilder str)
{
Console.WriteLine("open: {0}; close: {1}; str: {2}", open, close, str.ToString());
if (open == 0 && close == 0)
{
Console.WriteLine(str.ToString());
str.Clear();
}
if (open > 0)
{
CombiParentheses(open - 1, close + 1, str.Append("("));
}
if (close > 0)
{
CombiParentheses(open, close - 1, str.Append(")"));
}
}
public static void CombiParenthesesFixed(int open, int close, string str)
{
Console.WriteLine("open: {0}; close: {1}; str: {2}", open, close, str);
if (open == 0 && close == 0)
{
Console.WriteLine(str);
}
if (open > 0)
{
CombiParentheses(open - 1, close + 1, str + "(");
}
if (close > 0)
{
CombiParentheses(open, close - 1, str + ")");
}
}
私の直感では、それがJavaバージョンでは 'STRING'対StringBuilder''の利用に関連していることです。 'Append()'のような 'StringBuilder'の操作関数は、元の' StringBuilder'オブジェクト自体を返します。新しいものではありません。 – dotNET
@MitchWheat:どうか説明できますか?私はJavaのバージョンとの違いは他にありません。おそらくあなたはリンク先のポストで最適化されたバージョンを見ていますか? – dotNET
問題は、Javaバージョンが文字列を使用することです。文字列は不変です。文字列を使ってメソッドを再帰的に呼び出すと、再帰呼び出しで使用される新しい文字列インスタンスが作成されます。あなたはStringBuilderを使用し、毎回毎回同じインスタンスを渡します。あなたの最初のレコーディングを見てみましょう。 call:stringは 's +" {"'を呼び出しに渡します。同じ呼び出しだが、2番目のrec。コールは元の 's'' +'} 'を渡します。あなたのStringBuilderには、前に追加された中括弧が含まれます。 –