如何打印带括号的字符串的不同方式

时间:2016-05-23 20:24:13

标签: java recursion

我必须编写一个程序,它返回括号括起来的所有不同方法。例如,如果给定的字符串是“abcd”,那么我们将得到这五个不同的结果:

((ab)c)d     (a(bc))d     (ab)(cd)     a((bc)d)     a(b(cd))

括号的数量当然取决于字符串的长度,但我认为字符串-2的长度是合适的(我们不知道我们可以使用的括号数... )。这似乎很简单:我只需将括号插入每个可能的位置。我认为递归适用于此。

我试着写这个:

private static ArrayList<String> generateParens(String string, ArrayList<String> list, int leftRem, int rightRem, char[] str, int count) {
    if (leftRem < 0 || rightRem < leftRem) return null; 
    if (leftRem == 0 && rightRem == 0) { /* all out of left and right parentheses */
        String s = String.copyValueOf(str);
        list.add(s);
    } else {
        if (leftRem > 0) { // try a left paren, if there are some available
            str[count] = '(';
            str[count+1] = string.charAt(count); 
            generateParens(string, list, leftRem - 1, rightRem, str, count+1);
        }
        if (rightRem > leftRem) { // try a right paren, if there’s a matching left
            str[count] = string.charAt(count);
            str[count+1] = ')';
            generateParens(string, list, leftRem, rightRem - 1, str, count + 1);
        }
    }


    return list;
}

public static ArrayList<String> generateParens(String string) {
    char[] str = new char[string.length()*2]; //because we have a PAIR of parenthese
    ArrayList<String> list = new ArrayList<String>();
    String str2 = string + string;
    return generateParens(str2, list, string.length()-2, string.length()-2, str, 0);
}

我试着写一个递归函数,但我的递归效果不是很好,所以我遇到了很多问题,尤其是索引问题。我尝试了很多东西,但我仍然有问题;我不确定这是否仅仅是由于索引。)

你可以帮我解决一下吗?

1 个答案:

答案 0 :(得分:1)

您认为这是一个字符插入问题。我建议另一种观点。

将此视为代数表达式,可能是 a + b / c - d ,但没有运算符优先级规则。 必须找到所有可能的不同方法来计算:哪些操作分别是第一,第二和第三。查看它的另一种方法是,您必须构建具有四个叶节点的所有可能的二叉树。这给了我们表达式

((a+b)/c)-d    (a+(b/c))-d    (a+b)/(c-d)    a+((b/c)-d)    a+(b/(c-d))

我现在坚持使用代数的想法。你是正确的,你需要在任何完整的解决方案中准确地使用N-2对括号。你有N-1个操作,除了最后一个(最外面的操作符)之外的所有操作都需要一对括号。

我建议你从树的底部开始,然后继续前进。保留您必须加入的字符串列表。在每次迭代中,选择一对字符串进行连接;在它们周围加上括号,并用较短的列表重复。当列表只有两个项目时,您可以在没有最外面的括号的情况下连接它们。例如,在获取第二个字符串时,您的序列将使用括号(数组表示法?)作为列表:

private static genParen(leaves) // is the protocol.  Now for the execution sequence ...

call genParen(["a", "b", "c", "d"])
// Pick the second join ...
// Concatenate the 2nd & 3rd items; add parentheses
leaves[1] = "(" + leaves[1] + leaves[2] + ")"
// Delete item 2 from leaves, and recur:
  call genParen(["a", "(bc)", "d"])
  // This time, pick the first join ...
  leaves[0] = "(" + leaves[0] + leaves[1] + ")"
  // Delete item 1 from leaves, and recur:
    call genParen(["(a(bc))", "d"])
    // There are now only 2 elements remaining, so ...
    return leaves[0] + leaves[1]

现在,当您向上走回树时,您可以将每个解决方案添加到您维护的解决方案列表中。

“先选择”或“选择第二”连接逻辑不是挥手:你的函数必须依次遍历每个可能的选择:对于N个元素的列表,你有N-1个可能的选择。您必须使用较短的列表进行重复,并保存结果。

此外,您必须查看结果列表,因为有方法可以复制输出字符串。例如,有两种方法可以生成(ab)(cd),具体取决于您首先选择的单字母叶对。

这足以让你走向解决方案吗?