I implemented polygenelubricants's java code ( Valid Permutation of Parenthesis ) in C#.
My C# Code:
public static void CombiParentheses(int open, int close, StringBuilder str)
{
if (open == 0 && close == 0)
{
Console.WriteLine(str.ToString());
str.Clear();
}
if (open > 0) //when you open a new parentheses, then you have to close one parentheses to balance it out.
{
CombiParentheses(open - 1, close + 1, str.Append("{"));
}
if (close > 0)
{
CombiParentheses(open , close - 1, str.Append("}"));
}
}
However I'm getting the wrong result:
CombiParentheses(3, 0, tempString2);
{{{}}}
}{}}
}{}
}{{}}
}{}
What causes this difference between C# and Java implementation?
The issue is not in the Java->C# translation, but in the fact that you translated a string to a StringBuilder. When you call
str.Append("(");
You are appending "(" to the current string builder instance ( str
), and when you do
CombiParentheses(open - 1, close + 1, str.Append("("));
passing that instance itself on your method call, not a new instance.
An easy way to see the problem: suppose you're calling
CombiParentheses(2, 0, str);
When the second output string is written, the call stack will have been
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(")"));
Since you're using a single string builder instance, and you cleared it right before the call stack went into
CombiParentheses(1, 0, str.Append(")"));
The next output will match the output of that call, as if str had no characters on it yet , not the output you're expecting (which would be as if str still had a "("
on it).
If you used a string instead, when you do (string + ")")
, the result is a new string, not the same object that you modified, so the problem doesn't arise, when you get back to a CombiParentheses
call made earlier in the recursive execution you still have the original string that CombiParentheses
call received.
You can use this do see it in runtime:
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 + ")");
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.