4

Web サイトで機能するかどうかに関係なく、正規表現を使用してコーディングバットの問題を解決しようとしています。

*これまでのところ、 2 つの連続した等しい文字の間に a を追加しない次のコードがあります。代わりに、それらをブルドーザーで処理し、設定された文字列に置き換えます。

public String pairStar(String str) {
    Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    if(matcher.find())
    matcher.replaceAll(str);//this is where I don't know what to do
    return str;
}

正規表現を使い続けて文字列全体を置き換える方法を知りたいです。必要に応じて、再帰システムが役立つと思います。

4

4 に答える 4

2

これは機能します:

while(str.matches(".*(.)\\1.*")) {
    str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;

正規表現の説明:

検索正規表現(.)\\1

  • (.)「任意の文字」(.)を意味し、角かっこはグループを作成します-グループ1(最初の左角かっこ)
  • \\1、正規表現では\1(JavaリテラルStringは別のバックスラッシュでバックスラッシュをエスケープする必要があります)は「最初のグループ」を意味します-この種の用語は「バックリファレンス」と呼ばれます

つまり、一緒に(.)\1「繰り返される文字」を意味します


置換正規表現$1*$1

  • この$1用語は、「グループ1としてキャプチャされたコンテンツ」を意味します


再帰的ソリューション:

技術的には、そのサイトで要求されるソリューションは再帰的なソリューションであるため、ここに再帰的な実装があります。

public String pairStar(String str) {
    if (!str.matches(".*(.)\\1.*")) return str;
    return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}
于 2012-12-06T01:22:32.360 に答える
1

FWIW、ここに非再帰的な解決策があります:

public String pairStar(String str) {
  int len = str.length();
  StringBuilder sb = new StringBuilder(len*2);
  char last = '\0';
  for (int i=0; i < len; ++i) {
    char c = str.charAt(i);
    if (c == last) sb.append('*');
    sb.append(c);
    last = c;
  }
  return sb.toString();
}
于 2012-12-06T18:42:26.323 に答える
1

これは私自身の解決策です。

再帰的な解決策(問題が設計された解決策とほぼ同じです)

public String pairStar(String str) {
    if (str.length() <= 1) return str;
    else return str.charAt(0) +
                (str.charAt(0) == str.charAt(1) ? "*" : "") +
                pairStar(str.substring(1));
}

について不平を言いたい場合は、実際の再帰作業をsubstring行うヘルパー関数を作成できます。pairStar(String str, int index)

正規表現ワンライナーワンファンクションコールソリューション

public String pairStar(String str) {
  return str.replaceAll("(.)(?=\\1)", "$1*");
}

どちらのソリューションも同じ精神を持っています。どちらも現在の文字が次の文字と同じかどうかをチェックします。それらが同じ場合は*、2 つの同一の文字の間に a を挿入します。次に、次の文字の確認に進みます。これはa*a*a*a、 input から期待される出力を生成することaaaaです。

の通常の正規表現ソリューションに"(.)\\1"は問題があります。一致ごとに 2 文字を消費します。その結果、2文字目以降の文字が同一文字かどうかの比較に失敗しました。この問題を解決するために、先読みが使用されます。これは、次の文字を消費せずに比較します。

str.charAt(0) == str.charAt(1)これは、現在の文字のみを削除して部分文字列で関数を再帰的に呼び出しながら、次の文字を比較する再帰的なソリューションに似ていpairStar(str.substring(1)ます。

于 2013-05-08T20:04:03.510 に答える
1

私はJavaを知りませんが、Javaまたは正規表現で文字列を置換する機能があると思います。あなたの一致文字列は

([a-z])\\1

そして、置換文字列は次のようになります

$1*$1

いくつかの検索の後、私はあなたがこれを探していると思います、

str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");
于 2012-12-06T01:13:58.097 に答える