C#实现 - “打印平衡括号的所有组合”

时间:2017-03-14 05:31:58

标签: java c# recursion

我在C#中实现了polygenelubricants的java代码(Valid Permutation of Parenthesis)。

我的C#代码:

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("}"));
    }
}

但是我得到了错误的结果:

CombiParentheses(3, 0, tempString2);
{{{}}}
}{}}
}{}
}{{}}
}{}

导致C#和Java实现之间存在这种差异的原因是什么?

1 个答案:

答案 0 :(得分:2)

问题不在Java-> C#转换中,而在于您将字符串转换为StringBuilder。当你打电话

str.Append("(");

您正在追加"("到当前字符串构建器实例(str),并在您执行时

CombiParentheses(open - 1, close + 1, str.Append("("));

在方法调用中传递该实例本身,而不是新实例。

查看问题的简单方法:假设您正在调用

CombiParentheses(2, 0, str);

写入第二个输出字符串时,调用堆栈将是

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(")"));

由于您正在使用单个字符串构建器实例,并且在调用堆栈进入之前就已将其清除

CombiParentheses(1, 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 + ")");
    }
}