web-dev-qa-db-ja.com

アルゴリズムの比較と複雑さ

私はこの問題を解決したい:

N対の括弧のすべての有効な組み合わせを返すメソッドを記述します。

このメソッドは、文字列のArrayListを返す必要があります。各文字列は、括弧の有効な組み合わせを表します。

ArrayList内の文字列の順序は重要ではありません。

例:combParenthesis(2)==> {"(())"、 "()()"}

注:有効な組み合わせとは、括弧のペアが開いたままになっていないことを意味します。 ")()("は有効な組み合わせではありません。

私の最初の解決策は:

public static ArrayList<String> combParenthesis2(int pairs) {
    ArrayList<String> res = new ArrayList<String>();
    recursive(pairs, pairs, "", res);
    return res;
}

public static void recursive(int left, int right, String build, ArrayList<String> res) {
    if(right == 0 && left == 0) {
        res.add(build);
        return;
    }

    if(left > 0)
        recursive(left-1, right, build + "(", res);

    if(right > left)
        recursive(left, right-1, build + ")", res);
}

そして、複雑さはO(N ^ 2)だと思います、私は間違っていますか?

2番目のアルゴリズムは次のとおりです。

public static ArrayList<String> combParenthesis(int pairs) {
    Set<String> result = new HashSet<>();
    if (pairs <= 0) {
        return new ArrayList<>(result);
    }

    result.add("()");
    if (pairs == 1) {
        return new ArrayList<>(result);
    }

    for (int i=1; i<pairs; i++) {
        Set<String> newSet = new HashSet<>();
        for (String s : result) {
            newSet.add(s + "()");
            newSet.add("()" + s);
            newSet.add("(" + s + ")");
        }
        result = newSet;
    }

    return new ArrayList<>(result);
}

2番目のアルゴリズムの複雑さはどれですか?
どちらが好きで、なぜですか?

3
user72708

私はあなたが間違っていると思います

どのようにして複雑さn ^ 2になりましたか?最初のアプローチの複雑さはO(n!)であり、アルゴリズムは正しいです。

実際には、有効な組み合わせの数はC(n)です。 https://en.wikipedia.org/wiki/Catalan_number を参照してください。したがって、漸近的に複雑さはO(4 ^ n)です。

2番目のアプローチはより複雑(O(3 ^ n))ですが、正しくありません-間違った結果が生成されます。たとえば、間違った結果に「(())(())」が表示されません。

ですから、私は最初のアルゴリズムを好みます。それが正しいからです。

1
bohuss